How to query nested objects in firestore

24,585

Solution 1

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" });

Solution 2

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.

Share:
24,585
Niklas Raab
Author by

Niklas Raab

I am programming apps, with love and passion.

Updated on July 09, 2022

Comments

  • Niklas Raab
    Niklas Raab almost 2 years

    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()