Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to query nested objects in firestore [duplicate]

I want to store data in following format:

{
   "chatName": "Football",
   "chatMembers":
   [
      {
         "userId": "nSWnbKwL6GW9fqIQKREZENTdVyq2",
         "name": "Niklas"
      },
      {
         "userId": "V3QONGrVegQBnnINYHzXtnG1kXu1",
         "name": "Timo"
      },
   ]
} 

My goal is to get all chats, where the signed in user with a userId is in the chatMembers list. If the userId of the signed in user is not in the chatMembers property, then that chat should be ignored. Is this possible?

If this is not possible, how can i achive this with subcollections?

My development language is dart, but you can also post solutions in other languages.

My current attempt is this, but this is not working:

_firestore.collection(collectionName).where("chatMembers.userId", isEqualTo: userId).snapshots()
like image 447
Niklas Raab Avatar asked Oct 20 '18 12:10

Niklas Raab


People also ask

How do I query multiple values in firestore?

With the in query, you can query a specific field for multiple values (up to 10) in a single query. You do this by passing a list containing all the values you want to search for, and Cloud Firestore will match any document whose field equals one of those values.

How do I aggregate data in firestore?

If you want to gain insight into properties of the collection as a whole, you will need aggregation over a collection. Cloud Firestore does not support native aggregation queries. However, you can use client-side transactions or Cloud Functions to easily maintain aggregate information about your data.

What is a Subcollection in firestore?

A subcollection is a collection associated with a specific document. Note: You can query across subcollections with the same collection ID by using Collection Group Queries. You can create a subcollection called messages for every room document in your rooms collection: collections_bookmark rooms.


2 Answers

Since August 2018 there is the new array_contains operator which allows filtering based on array values. The doc is here: https://firebase.google.com/docs/firestore/query-data/queries#array_membership

It works very well with arrays of string. However, I think it is not possible to query for a specific property of an object stored in the array. One workaround is to query for the entire object, as follows (in Javascript). Of course this may not be feasible in every situation....

    var db = firebase.firestore();
    var query = db.collection('chatDocs').where("chatMembers", "array-contains", { userId: "xyz", userName: "abc" });
like image 125
Renaud Tarnec Avatar answered Oct 05 '22 22:10

Renaud Tarnec


Renaud Tarnec's, which complete, doesn't work in every case. Situations where only one or not all of the fields are known won't return the expected documents. However, by restructuring the data in the document, a query can be made to work where only one field is known, like a user identifier (uid).

Here's the data structure inside one of the document:

{
  "members": {
    "user4": {
      "active": true,
      "userName": "King Edward III",
      "avatar": "www.photos.gov/animeGirl5.png"
    },
    "user7": {
      "active": true,
      "userName": "Dave K.",
      "avatar": "www.photos.gov/gunsAmericanFlag.png"
    }
  }

Here's the query:

uid = 'user4';
collectionQuery = collectionReference.where(`members.${uid}.active`,"==", true);

In this example, "user4" represents a user who may or may not be in a group. This will return all documents in the collection where the uid "user4" is an active member. This works by only needing to know the UID of the member and works without needing to know their name or avatar uri ahead of time.

like image 23
Brett S Avatar answered Oct 05 '22 23:10

Brett S