0

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?

Community
  • 1
  • 1
Jamie T
  • 31
  • 1
  • 6
  • If I get you right, that should work. I once had a project with few friends and we did the same thing, that we stored our tags in an array that was in a users document. – Constantin Beer Aug 27 '19 at 18:13
  • I'm not sure if `arrayContains` can take an array as a parameter, I believe it takes only single strings. That's how I use it on my case though. – Rodolfo Franco Aug 28 '19 at 01:10
  • How do you compare multiple tags to multiple tags and get a query return. – Jamie T Aug 28 '19 at 16:18

2 Answers2

1

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.
  • I am not looking for a solution where the game contains both the leafs and the Canadiens, I am looking for a solution where it contains _Either_ team not Both. I want to query all stories involving the leafs OR the canadiens Does the sample code work for or? – Jamie T Sep 04 '19 at 17:55
0

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!