0

I used to have a document with the following structure:

OldDoc:

members: ['userId1', 'userId2', 'userId3']

I then wrote a query to retrieve all documents relevant to a user:

const docsSnapshot = await getDocs(query(
    collection(db, 'organisations'),
    where('members', 'array-contains', user.uid)
))

This worked well, but now I need to store the user's names in as well as:

members: [{ id: 'userId1', name: 'John Smith' }, { id: 'userId2', name: 'Jane Smith' }]

The challenge I'm facing is that I'm not sure how to construct a query that would yield the same results as the first one - i.e., how do I retrieve all docs where any of the objects have an id attribute corresponding to user.uid.

I tried using: where('members.id', '==', user.uid) but that didn't work.

Can a query be constructed to do this?

Sam
  • 1,130
  • 12
  • 36
  • See https://stackoverflow.com/questions/54081799/firestore-to-query-by-an-arrays-field-value/54082731#54082731 – Renaud Tarnec May 09 '22 at 09:10
  • if you add all members in the same doc is going to be hard later, you need to do a document for each memeber, even if they hold 2 values, and add the doc name their uid as `setDoc(doc(db, "organisations", uid), {name: ...., uid:...})` or make a subcollection `setDoc(doc(db, "organsiations", "members", "subcollection", uid), {.....data...})` – codmitu May 09 '22 at 09:17
  • I'm trying to avoid creating a doc for each member because I'm building a page which displays all members of an organisation, and I don't want to incur cost of a read for each member in an org every time an org is displayed. – Sam May 09 '22 at 09:47

1 Answers1

1

Firestore isn't great at these kinds of queries... I'd consider restructuring your member array to be an object with user.id as keys.

members : {
   userId1: { name: "fred" },
   userId2: { name: "martha" }
}

Another way, and perhaps more closely aligned to how Firestore 'wants' you to do it, would be to create another subcollection members with a new document for each member with the doc.id set to the user.id.

This approach also allows you to easily add more data to each member, with the added benefit of making queries on members that don't just rely on the user.id.

John Detlefs
  • 952
  • 8
  • 16
  • I'm trying to avoid the second approach as to not incur read cost for every individual user when I'm trying to get a list of users with basic info. The first approach of restructuring the data looks promising though. How would I write a query to check if `user.uid` exists as an object key in the `members` object? I tried `where(`members.${user.uid}`, '!=', null)` but that returns always returns all documents. `where('members', 'in', user.uid)` display any. – Sam May 09 '22 at 09:57
  • On phone, so tricky editing but `collection.orderBy(members.userId1)` should do the trick I think? – John Detlefs May 09 '22 at 10:11
  • I was actually wrong. `where(``members.${user.uid}``, '!=', null)` works perfectly fine. Thanks for your help! – Sam May 09 '22 at 10:13