Home > Mobile >  How to properly chain Firestore queries using checkboxes
How to properly chain Firestore queries using checkboxes

Time:03-28

Context

I'm trying to create a document list view with a filter sidebar. The documents are stored in Firestore and I'm using Nuxt with Vuex to fetch and store the documents.

export const getters = {
  plants: (state) => state.plants
}

export const mutations = {
  SET_PLANTS(state, payload) {
    state.plants = payload
  }
}

export const actions = {
  async fetchPlants({ commit }, queryArray) {
    const docsRef = collection(db, 'plants')
    let snapshot;

    if (queryArray) {
      const q = query(docsRef, where(...queryArray))
      snapshot = await getDocs(q)
    } else {
      snapshot = await getDocs(docsRef)
    }
    const results = []

    snapshot.forEach((doc) => {
      results.push({ ...doc.data(), id: doc.id })
    })

    commit('SET_PLANTS', results)
  }
}

Then, in my ListView component I fetch the data:

export default {
   async fetch({ store }) {
    try {
      await store.dispatch('plants/fetchPlants')
    } catch (err) {
      console.log(err)
    }
  },
  computed: {
    plants() {
      return this.$store.getters['plants/plants']
    }
  }
}

And use a simple v-for loop to output the data:

<div v-for="plant in plants" :key="plant.id">
   <h3>{{ plant.name }}</h3>
   <p>{{ plant.description }}</p>
   <span v-for="(value, index) in plant.properties" :key="index">
      {{ value }}
   </span>
</div>

Notice the nested v-for loop that takes in the plant's properties. These consist of stuff like 'Needs little water', 'Needs little sun' etc.

The question

I would like to create a filter sidebar in the ListView component that allows the user to filter the plants based on their properties using a checkbox for each of them.

As you might have seen, I already have a queryArray parameter setup inside the fetchPlants action:

if (queryArray) {
  const q = query(docsRef, where(...queryArray))
  snapshot = await getDocs(q)
}

This parameter could look something like this: ['water', '==', 'Needs little water']

However, this setup only allows for 1 filter to be applied. How do I properly chain multiple where() clauses together using checkboxes?

CodePudding user response:

If your queryArray looks like this:

const queryArray = [
  ['water', '==', 'Needs little water'],
  ['light', '==', 'Needs little sunlight'],
]

Then you'll have to add a where() for each field as shown below:

const q = query(docsRef, ...queryArray.map((item) => where(item[0], item[1], item[2])))
  • Related