How to use array-contains operator with an array of objects in Firestore?

Viewed 2406

So, i want to query some data from firestore.

this is my data structure

enter image description here

so, the collection is Modules, then i now have 2 documents but it will be 75 or something. Then in that document i want to get the specific document which has a specific LessonId (In this example '2') How do i query this?

this is wat i tries but it's not working for me

    async function getModuleData() {
        let ModuleData = await firebase
            .firestore()
            .collection('Modules')
            .where('Lessons', 'array-contains', {LessonId: 2})
            .get()
            .then(snapshot => {
                snapshot.forEach(doc => {
                    console.log(doc.data())
                })
            });
   } getModuleData()

when i do this

    async function getModuleData() {
        let ModuleData = await firebase
            .firestore()
            .collection('Modules')
            .where('Title', '==', 'Leven vanuit verlossing')
            .get()
            .then(snapshot => {
                snapshot.forEach(doc => {
                    console.log(doc.data())
                })
            });
   } getModuleData()

it just works so it's something with my where statement i guess?

2 Answers

To use array-contains with an array of objects, you need to pass the complete object you are looking for in that array.

For example,

const lessonObj = {
  Title: "Leven vanuit verlossing",
  Description: "the desc",
  ...allTheOtherFieldsAsIs
}
firebase.firestore().collection("Modules").where("Lessons", "array-contains", lessonObj)

You should ideally use a sub-collection to store lessons in a module. Then you can easily query lessons using the following query:

const db = firebase.firestore()

const lessonsSnapshot = await db.collection("Modules")
                          .doc("moduleID")
                          .collection("Lessons")
                          .where("Title", "==", "Leven vanuit verlossing")
                          .get()

console.log(lessonsSnapshot.docs[0].data())

As Dharmaraj answered, the array-contains operator performs a complete match, so it only returns documents where the array contains the exact value you specified.

If you only want to filter on lesson IDs, I'd recommend adding an additional field to each document with just the lesson IDs. You can then filter on that field with:

firebase
        .firestore()
        .collection('Modules')
        .where('LessonsIDs', 'array-contains', 2)
Related