Firestore Query Across Multiple Fields for Same Value

Firestore query for same value in multiple fields

For an OR condition we've to do multiple queries like this:

//We define an async function that takes user uid and return chats
async function getChatsByUserOrOwner(userId) {
const chatsRef=firestore().collection('chats')
const ownerChats = chatsRef.where('ownerUserId', '==', userId).orderBy('createdAt', 'desc').get();
const userChats = chatsRef.where('chatUserId', '==', userId).orderBy('createdAt', 'desc').get();
const [ownerChatsSnapshot, userChatsSnapshot] = await Promise.all([
ownerChats,
userChats
]);
const ownerChatsList = ownerChatsSnapshot.docs;
const userChatsList = userChatsSnapshot.docs;
const allChats = ownerChatsList.concat(userChatsList);
return allChats;
}

Now we'll call this function to get required result:

//We call the asychronous function
getChatsByUserOrOwner(user.uid).then(result => {
result.forEach(docSnapshot => {
console.log(docSnapshot.data());
});
});

Firestore Query Across Multiple Fields for Same Value

Firestore doesn't support substring, regular expression, or full text search types of queries. Those kind of searches don't scale with the way Firestore manages its indexes.

If you need fully text searching, consider duplicating your data into a search engine such as Algolia. This type of solution is discussed in the Firebase docs.

FireStore - Multiple isEqualTo/== query on a single field

There are two ways to do what you want:

  1. With a range query: ref.where("price", ">=", 97).where("price", "M=", 99)

  2. With an in query: ref.where("price", "in", [97, 98, 99])

For more information on both, see the Firebase documentation on queries.

Query multiple Firestore Collections for same field

You could use Promise.all() to execute all the queries in parallel, as follows:

   const db = firebase.firestore();

const q1 = db.collection('creators').where('description', '==', '...').get();
const q2 = db.collection('xyz').where('description', '==', '...').get();

return Promise.all([q1, q2])
.then(snapshotsArray => {

snapshotsArray.forEach(snap => {
snap.forEach(doc => {
console.log(doc.id, '=>', doc.data())
})
})

})

You could simplify it as follows:

   const collectionNames = ['creators', 'klmn', 'opqr', 'stuv']
const promises = collectionNames.map(x => db.collection(x).where('description', '==', '...').get());

Promise.all(promises)
.then(snapshotsArray => {

snapshotsArray.forEach(snap => {
snap.forEach(doc => {
console.log(doc.id, '=>', doc.data())
})
})

})

As explained in the doc referred to above:

The Promise.all() method returns a single Promise that fulfills when
all of the promises passed as an iterable have been fulfilled

...

The returned promise is fulfilled with an array containing all the
values of the iterable passed as argument (also non-promise values).


HOWEVER,

there is an important point to note, based on this sentence in your question: "find documents across several Collections where they have documents with no description field".

You cannot build a query in Firestore that will return document without a given field. The reason (indexing mechanism) is well explained in this official video .

On the other hand, you can query for a document with an empty field:

db.collection('creators').where('description', '==', '').get();

or with a field with null value:

db.collection('creators').where('description', '==', null).get();

Search with multi fields firestore

If you're asking if it's possible to accept a single string and search across fields with it, no it's not possible. Firestore isn't a text search engine.

The only way you can query across fields is using a compound search query as described in that documentation. You have to call out each field you want to match, and you can only have one range filter per query (so you can't use startAt/EndAt with multiple fields). You will need to use the exact values of the fields to filter the results.

If you want full text search, the documentation recommends mirroring your data to an actual text search engine.

Can I filter Multiple Fields in a Firestore search?

No, you cannot do this.

Looking at the Firebase Firestore Documentation page about queries, you will find out about the following:

Cloud Firestore does not support the following types of queries:

  • Queries with range filters on different fields, as described in the previous section.

This does not directly apply to your specific use case, but the reasoning for why your request will not work is similar: There is no index that allows you to sort according to multiple different fields.

You could e.g. create indexes that sort each of the fields, but only query them individually. To understand why certain queries are not supported, you can check out this in depth explanatory video from the Firebase team.

Concluding, this means that you will need to do the filtering client side.

Workaround Concept in Flutter

final QuerySnapshot querySnapshot = 
await Firestore.instance.collection('cakes').getDocuments();
final List<DocumentSnapshot> documents =
querySnapshot.documents.where((snapshot) => snapshot.data.containsValue('cheesecake'));
// now the [documents] object will only contain documents, which have "cheesecake" as any of their fields

Query Firestore field/value using multiple multiple 'where' values?

You should use the in operator: "Use the in operator to combine up to 10 equality (==) clauses on the same field with a logical OR. An in query returns documents where the given field matches any of the comparison values".

var usersFollowed = ['GKXgK2CPPGPQjmQ3Lsrh', 'cBjzo3MSjjaOHksVmO0o', 'tc9gMwZR9SiyjWonyCWF'];
var followingPosts = await db.collection('posts').where('posterUID', 'in', usersFollowed).get();

However, note that you can only combine up to 10 equality (==) clauses.

If you need to combine more than 10 clauses, you will need to do several similar queries and merge the results. This article explains how to merge two queries with the JS SDK.

How can I query multiple fields on a single map data in Firestore?

I tried to put data in array but currently firebase Array membership only support filtering one item in the array.

You're right, you can filter your items only by a single item that exist in an array. If you'll chain more than one function call, you'll get an error similar with this:

Invalid Query. Queries only support having a single array-contains filter.

And to answer your question:

But is there any way to query on multiple fields to get a document which contains a subject hash at any given number of subjects?

Unfortunately, there are no wildcards in Firestore. You have to identify the property names of your documents by their exact property name.

If you want to limit the results by filtering on multiple properties, you need to chain where() functions, like in the following example:

ref.where('subject.math', '==' , true)
.where('subject.science', '==' , true)
.where('language.english', '==' , true)

Firestore - Query multiple fields

You can create a composite field that contains all the data you need for the query by concatenating both user IDs into a single string. Be sure to sort the IDs before doing so, in order to ensure that they have a predictable order.

So, if you have user "A" and user "B", your composite field value would be simply "AB" (and never "BA"), and you can filter on this field to find all message between these two users.



Related Topics



Leave a reply



Submit