Firestore query comparing two arrays without array-contains

Viewed 1719

Is it possible to compare two arrays in a Firestore query without 'array-contains'?

Something like this:

    query = query.where(
       "info.currentLocation",
       "==",
       currentUserBasicInfo.currentLocation
    );

info.currentLocation and currentUserBasicInfo.currentLocation are both arrays with mapped values. I can't change the data structure and I already have an 'array-contains' in the query. Because the two arrays have to be identical for this to run, I feel like there has to be a way to compare two arrays without having to use 'array-contains' or 'array-contains-any' or 'IN'.

Any suggestions? Is this possible?

2 Answers

The Problem

What you need is something similar to array-contains-all.

So let's say that in firebase you have this:

enter image description here

And then in your code you have something like this:

const usersIDs = [
  'q4nemfzg19OCmwm1EauiZwdYD4z1',
  'UzmgPRtlRSZX44erF6VrkYQ5Kyf1',
];

Then you want to compare with something like this:

yourCollectionRef.where('users', 'array-contains-all', usersIDs).get()
// or 
yourCollectionRef.where('users', '==', usersIDs).get()

But this is currently not possible. The array-contains-all is still a requested feature and the == is not gonna work.

The Solution

So the good news is that I have a solution for you in case you are willing to change your collection structure.

Instead of saving the data in array, save it in a map object and the items would be the keys.

Like this:

enter image description here

And then you can easily use the filter == as you want. Of course you can transform the array into a map object or simply have it like this:

const usersMap = {
  q4nemfzg19OCmwm1EauiZwdYD4z1: null,
  UzmgPRtlRSZX44erF6VrkYQ5Kyf1: null,
};

And this would be your final query:

yourCollectionRef.where('usersMap', '==', usersMap).get();

Then if you need in the future to get all of the documents from a specific user that's inside the usersMap you can use this query here:

yourCollectionRef.where(`usersMap.${userId}`, '==', null).get();

"array-contains" method has ability to query for elements within arrays[1]. This means you can keep your elements as an array, and easily query for them without having to resort to the map hack.

If you don't want to use this method one alternative could be iterate both arrays until match the values as you need.

However, in this document[2] you can find multiple examples for perform simple and compound queries.

[1] https://firebase.google.com/docs/firestore/query-data/queries

[2] https://firebase.googleblog.com/2018/08/better-arrays-in-cloud-firestore.html

Related