3

I am having troubles with firebase using the cloudstore .where query. I want to query a big collection of documents (in my case posts) but I only want to query the posts in which the groupId matches any of the groups that the user is in. The reason for this is that I want to query a combined feed for the user with all the latest relevant data (using orderBy and limit).

I know that I can use array-contains, so I could for instance query all of the posts for user where the user is a member.

firebase.db.collection('posts').where('members','array-contains',firebase.uid)

This would work if I decided to keep track of the members in a group. Problem is if I would change members in a group, I would have to loop through all posts and change the array of members (not really good practice). Better would then be to have the post contain and id of which group it was posted in.

So let's say the user has an array containing all the groups he is in

user.groups = ['companyGroup', '{id}', '{id2}']

I would then like to query through the whole posts collection and get all the documents where the field groupId matches any of the values in user.groups something like this:

firebase.db.collection('posts').where('groupId','==',[any of user.groups])

or maybe the reverse:

firebase.db.collection('posts').where(user.groups,'array-contains','groupId')

^ I have not tried this one but I am certain it doesn't work according to the docs according to

The where() method takes three parameters: a field to filter on, a comparison operation, and a value. The comparison can be <, <=, ==, >, >=, or array_contains.

Is there a possible way to do something like this? I can't really query multiple locations at once and combine them because that defeats the purpose of being able to limit the data and orderBy fields. I understand that I could put a new collection called feed under every user and for every post use a firebase function that pushes to post to the relevant members feed (only the id and latestActivity), but then as soon as that post changes (I am going to use a field called latestActivity to order data according to relevancy, but also when deleting a post) I would need to loop through all docs under every user affected and change the value/delete doc.

Any ideas are greatly appreciated!

Martin Kjellberg
  • 615
  • 1
  • 6
  • 22

2 Answers2

2

Currently, there is no way to pass an array of ids to the where() function and expect to get all the documents that corresponde to each particular id:

firebase.db.collection('posts').where('groupId','==',[any of user.groups])

The option that you have, is to store in the array either the ids as strings or references (path to group documents). There is no real advantage of storing references rather than strings, so it's up to you to decide which one you feel more comfortable with.

To get the all group documents, you should get the array that contains those ids/references and for each one separately create a new database request. So unfortunately there is no other way to get those group documents at once using a single query.

However, creating extra database calls it doesn't mean that fetching, let's say 3 documents, will be 3x slower as fetching one document. You can make some tests yourself.

I quote @Frank van Puffelen, "Firebase has a history of performing fine in such cases, since it pipelines the requests."

Alex Mamo
  • 130,605
  • 17
  • 163
  • 193
  • Great answer Alex! The thing that makes it a bit tricky with calling multiple collections is how I would 'mark' my posts. Let's say I have 20 posts in the company group and 1 post in another group from 1 month ago and I want to fetch the feed for the user. I fetch the 5 latest posts from each group but this will then show 5 posts from the company group and 1 post from the other group while there are 15 posts in between. Also when we will fetch more posts after user scrolls down it is also a bit tricky. But you're right I could handle this some way client side - maybe it is doable. – Martin Kjellberg Feb 12 '19 at 08:41
  • In that case, you should consider augmenting your data structure to allow a reverse lookup. This means that you should duplicate data so you can query the database only for those objects you are interested in. Thank you too. – Alex Mamo Feb 12 '19 at 09:28
-1

use array contain it works perfectly.

firebase.db.collection('posts').where(user.groups,'array-contains','groupId') it works pretty good for me . you should try this.

  • Just tried this one and doesn't work. It works perfectly if I would match documents where the field is an array and it contains my value, but doing it with this code above (the reverse) doesn't seem to work. – Martin Kjellberg Feb 07 '19 at 16:51
  • firebase.db.collection('posts').where(array in your data base,'array-contains','groupId') – Muhammad Abdullah Feb 07 '19 at 16:54
  • put the name of array – Muhammad Abdullah Feb 07 '19 at 16:54
  • yes that works for that case, but what I am looking for is the reverse thing. Query a collection where a field matches any of the strings I have in my array (client side). So the field value on the document is a string, not an array. Basically: firebase.db.collection('posts').where(string in my database, '==', one of the objects from my array) – Martin Kjellberg Feb 07 '19 at 17:55