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