angular - Firebase query if child of child contains a value -
the structure of table is:
- chats
- --> randomid
- -->--> participants
- -->-->--> 0: 'name1'
- -->-->--> 1: 'name2'
- -->--> chatitems
etc
what trying query chats table find chats hold participant passed in username string.
here have far:
subscribechats(username: string) { return this.af.database.list('chats', { query: { orderbychild: 'participants', equalto: username, // how check if participants contain username } }); }
a few problems here:
- you're storing set array
- you can index on fixed paths
set vs array
a chat can have multiple participants, modelled array. not ideal data structure. each participant can in chat once. using array, have:
participants: ["puf", "puf"] that not have in mind, data structure allows it. can try secure in code , security rules, easier if start data structure implicitly matches model better.
my rule of thumb: if find writing array.contains(), should using set.
a set structure each child can present @ once, naturally protects against duplicates. in firebase you'd model set as:
participants: { "puf": true } the true here dummy value: important thing we've moved name key. if i'd try join chat again, noop:
participants: { "puf": true } and when you'd join:
participants: { "john": true, "puf": true } this direct representation of requirement: collection can contain each participant once.
you can index fixed paths
with above structure, could query chats in with:
ref.child("chats").orderbychild("participants/john").equalto(true) the problem require define index on `participants/john":
{ "rules": { "chats": { "$chatid": { "participants": { ".indexon": ["john", "puf"] } } } } } this work , perform great. each time new joins chat app, you'll need add index. that's not scaleable model. we'll need change our data structure allow query want.
invert index - pull categories up, flattening tree
second rule of thumb: model data reflect show in app.
since looking show list of chat rooms user, store chat rooms each user:
userchatrooms: { john: { chatroom1: true, chatroom2: true }, puf: { chatroom1: true, chatroom3: true } } now can determine list of chat rooms with:
ref.child("userchatrooms").child("john") and loop on keys each room.
you'll have 2 relevant lists in app:
- the list of chat rooms specific user
- the list of participants in specific chat room
in case you'll have both lists in database.
chatroomusers chatroom1 user1: true user2: true chatroom2 user1: true user3: true userchatrooms user1: chatroom1: true chatroom2: true user2: chatroom1: true user2: chatroom2: true i've pulled both lists top-level of tree, since firebase recommends against nesting data.
having both lists normal in nosql solutions. in example above we'd refer userchatrooms inverted index of chatroomsusers.
Comments
Post a Comment