Querying arrays within documents in Google Firestore

Viewed 102

I have a document in a collection which has an array of objects as a property.

e.g.

Projects
   name: 'Great Project'
   members: [{id:'1', name:'rob']

I want to get all projects with rob as a member.

I was hoping this would work

collection("projects")
    .where("members.name", "array-contains", "rob")
   

...but nope.

As you can see, I'm trying to get the ID

I suppose I could use a sub collection, but then I'd have a similar issue.

What am I doing wrong!

And, is this the best way to store this data?

1 Answers

Your query currently looks for documents where the field owners is a map with a nested array of string names having rob in it. But in your sample document the field with array of objects is members. To use array-contains with an array of objects, you need to pass in the complete object as is:

const owner = {id: '1', name: 'rob'}

const db = firebase.firestore()
const projectsCol = db.collection("projects")

const query = projectsCol.where("members", "array-contains", owner)

That being said, you need to know the id field present in the object as well.

You could move members to a sub-collection instead of an array and use Collection Group queries. The database structure would look something like:

projects -> {projectId} -> members -> {memberId}

Each document in members subcollection would be similar to:

{
  id: "1",
  name: "rob",
  ...otherFields
}

Now you can run a collection group query on "members" which will return all documents where the name is "rob" and then you can use DocumentReference to all matches documents to get the project ID.

const query = firebase.firestore().collectionGroup("members").where("name", "==", "rob")

query.get().then((snapshot) => {
  console.log(snapshot.docs.map(d => d.ref.parent.parent.id))
})

This should log IDs of projects where the rob is a member.

Related