Reputation: 31
I want to have a user select several sports teams from an NHL list or more specifically firebase to act like tags.
In a document I want to include an array that might have the tags of a story, #leafs, #senators #nhl.
Now I want to have the user interested in say #leafs #canadiens #nhl #ohl
I plan on storing the two in an array,
in Flutter
interestArray = ["leafs","canadiens",nhl,"ohl"]
So how do I,
get from Firebase interestArray from the array field "storyTags"?
.where('storyTags', arrayContains: interestArray )
Is this supposed to work?
Upvotes: 0
Views: 5775
Reputation: 11
We recently announced that Cloud Firestore supports two new kinds of queries: "in
" and "array-contains-any
". They let you find documents with any of several values (up to 10).
That might help!
Upvotes: 0
Reputation: 44
Unfortunately, 'arrayContains' can only take a single value, rather than an array. So you could test .where('storyTags', arrayContains: 'leafs')
but not 'leafs', 'canadiens'
However, a similar question has been asked before: Firestore search array contains for multiple values. (tl;dr: Use a map.)
Adapting that solution might result in a schema like:
Stories:
<docid>:
title: "Leafs to play Canadiens"
tags: {
"leafs": true,
"canadiens": true,
"nhl": true
}
And then to query it for all stories involving both the leafs and the canadiens, you'd use something like:
db.collection("Stories")
.where("tags.leafs", "==", true)
.where("tags.canadiens", "==", true);
(Note that Firestore does not support logical 'OR' queries; to do that, you'd need to issue separate queries and then merge the results. https://firebase.google.com/docs/firestore/query-data/queries#query_limitations)
Update in response to comment:
As mentioned above, it's unfortunately not possible to perform a logical 'OR' query. So to fetch all stories tagged with either team, you'd need to do something like this (in javascript):
var leafsSnapshot = await db.collection("Stories").where("tags.leafs", "==", true).get();
var habsSnapshot = await db.collection("Stories").where("tags.canadiens", "==", true).get();
// Concatenate the results together and log the story titles.
var stories = leafsSnapshot.docs.concat(habsSnapshot.docs);
// This won't quite work:
//
// stories.forEach(story => console.log(story.get("title")));
//
// It won't de-duplicate stories, so any story that's tagged with *both*
// will be printed twice.
var seen = new Set([])
stories.forEach(story => {
if (!seen.has(story.id)) {
seen.add(story.id);
console.log(story.get("title"));
}
});
Alternatively, if you're not interested in 'AND' queries, you could go back to using arrayContains and follow a similar approach as above. i.e.:
var leafsSnapshot = await db.collection("Stories").where("storyTags", "arrayContains", "leafs").get();
// the rest is the same.
Upvotes: 1