Firestore: How to query a map object inside a collection of documents?

14,004

Solution 1

Now you can filter ...

db
  .collection('orders')
  .where('orderDetails.status', '==', 'OPEN')

It will check if field orderDetails at property status equals to 'OPEN'

Solution 2

You cannot achieve this with your actual database structure in a way that you don't need to create an index for each user separately. To sovle this, you should duplicate your data. This practice is called denormalization and is a common practice when it comes to Firebase. If you are new to NoQSL databases, I recommend you see this video, Denormalization is normal with the Firebase Database for a better understanding. It is for Firebase realtime database but same rules apply to Cloud Firestore.

Also, when you are duplicating data, there is one thing that need to keep in mind. In the same way you are adding data, you need to maintain it. With other words, if you want to update/detele an item, you need to do it in every place that it exists.

That being said, you should create another collection named userStories, where you should add as documents all stories where a user is owner. So you database structure should look similar to this:

Firestore-root
   |
   --- userStories (collection)
         |
         --- uid (document)
              |
              --- allStories (collection)
                     |
                     --- storyId
                           |
                           --- role: "owner"

So a query like this:

db.collection('userStories').doc(${uid})
    .collection('allStories').where(`role`, '==', 'owner');

Will work perfectly fine.

Solution 3

enter image description herePlease let me know if I'm mistaken, but it appears that your query should actually work. as an experiment I added the structure you gave in the question and performed the query successfully in the firebase console.

Is this not what you are going for? I also made sure that the "in" operator works for this case as well. In this way you could ask which stories the user is owner & commenter.

enter image description here

This pulls in the correct results: enter image description here

Share:
14,004
Jek
Author by

Jek

Updated on June 08, 2022

Comments

  • Jek
    Jek about 2 years

    My objective:

    The web app (similar to Google Drive) has 2 screens.

    First screen is 'My Story' which displays all the story documents whom I'm the owner.

    Second screen is 'Shared with me' which displays all the story documents that I'm either reader, writer, or commenter.

    We have this /stories/{storyid}

    {
      title: "A Great Story",
      content: "Once upon a time ...",
      roles: {
        alice: "owner",
        bob: "reader",
        david: "writer",
        jane: "commenter"
        // ...
      }
    }
    

    Full data structure reference: https://firebase.google.com/docs/firestore/solutions/role-based-access

    Question: How to write the below query to fulfil the above objective?

    db
    .collection('stories')
    .where(`roles.${uid}`, '==', 'owner')
    

    The above query does NOT work because it will require Firestore to index roles.alice, roles.bob, roles.david, roles.jane, and roles.[all_uid].


    Edit #1: Found a related post (with no answers) asking about Firestore querying with roles

  • Jek
    Jek over 5 years
    could you comment on my answer. I think I know the answer to my question.
  • Jek
    Jek over 5 years
    @DougStevenson what do you think of this answer?
  • Alex Mamo
    Alex Mamo over 5 years
    No, that's not an option since you are duplicating data inside the same document. In this case, what about finding all stories jane == commenter? When we duplicate data, we duplicate the entire document, so we can copy the exact same data that already exists in one place, in another place, to suit queries that may not even be possible otherwise. Which is exactly your case.
  • Alex Mamo
    Alex Mamo over 5 years
    Please see my comment above. So I'll stick with this answer.
  • Jek
    Jek over 5 years
    What motivates you to answer questions on SO? Just curious. Does Google/Firebase pay you for each successful answer?
  • Alex Mamo
    Alex Mamo over 5 years
    @choopage-JekBao No. I was also once helped and I'd like to help others in the same way ;)
  • Jek
    Jek over 4 years
    Do you have index on it?
  • Grahambo
    Grahambo over 4 years
    No. Nothing extra was configured to make this work. This works out of the box in this example.
  • mrdev
    mrdev almost 4 years
    this's what i'm looking for.
  • Joao Gavazzi
    Joao Gavazzi about 3 years
    That actually seems to work, I've just done a test with the same data structure and everything seems fine.