how to search a document where members map contains a particular map_id
chatRoom: {
MVyMPi78DOwVQ5w5GnYe: {
...
members: {
<member_1_id>: {
id: xxxxx,
unreadmessagecount: xx
},
<member_2_id>: {
id: xxxxx,
unreadmessagecount: xx
}
},
La234Pi78DOwVQ5w5GnYe: {
...
members: {
<member_1_id>: {
id: xxxxx,
unreadmessagecount: xx
},
<member_2_id>: {
id: xxxxx,
unreadmessagecount: xx
}
}
}
like for above structure get all chatrooms where members
map
contains member_id
assume member_id
is known
CodePudding user response:
You can use dot notation to query documents based on nested field as shown below:
const q = query(collection(db, 'chatRoom'), where('members.user1', '==', {<obj>}))
This won't work for your use-case unless you know the exact object i.e. { uid: 'user1', unreadMessageCount: 1 }
.
As a workaround, you can use orderBy()
clause that'll only return documents where the field exists like this:
const q = query(collection(db, 'chatRoom'), orderBy('members.user1'))
However, this is actually querying the whole collection and so writing security rules will be a bit difficult. For example, if you use allow read: if request.auth.uid in resource.data.members
, the rule will fail as there will be many documents where this returns false.
I would recommend using storing all members' UIDs in an array as follows:
{
...
group: false,
memberIds: ['user_1_uid', 'user_3_uid']
}
Then you can use array-contains
operator to query all chat rooms of a user like this:
const q = query(collection(db, 'chatRoom'), where('memberIds', 'array-contains', 'some_uid'))
Then you can use the following security rules to ensure only a chat member can read/write the document:
allow read, write: if request.auth.uid in resource.data.memberIds