Eduard
Eduard

Reputation: 3576

Firestore range query on map field

I have a collection of conversations, each conversation having a hidden<Map> where each participant is the key, having a boolean value, so I can see if he archived the conversation on his end or not. Therefore, the query looks like this:

store.conversations
    .where( 'participants', 'array-contains', uid )
    .where( `hidden.${uid}`, '==', false )
    .orderBy( 'createdAt', 'desc' )

Problem rises when adding orderBy, which makes it a "range" query. So, given each document has a different set of keys in the hidden<Map>, Firestore is suggesting the following, which obviously wouldn't work:

participants Arrays 
hidden.`48m6lKjwvKUOboAxlc0ppX2R7qF2` Ascending 
createdAt Descending

How do I go around this? I guess flattening the Map would be a solution but, not most elegant. Any advice?

Upvotes: 1

Views: 208

Answers (1)

Alex Mamo
Alex Mamo

Reputation: 138824

Firestore is suggesting the following, which obviously wouldn't work:

participants Arrays 
hidden.`48m6lKjwvKUOboAxlc0ppX2R7qF2` Ascending 
createdAt Descending

You can create such an index and it will work but the problem rises if your app becomes popular and you'll have you'll have a big number of users. This means that for every conversation you'll have to create an index and this is not such a good idea because when it comes to indexes, there are some limitations. According to the official documentation regarding Firestore usage and limits:

Maximum number of composite indexes for a database: 200

Number that can be reached very quickly.

I guess flattening the Map would be a solution

You're guessing right. This practice is also 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.

For more information please also see my answer from the following post:

So you can denormalize your database and create conversations without the need of creating indexes. For your use-case, you should consider augmenting your data structure to allow a reverse lookup by creating a new collection or subcollection named userConversations that can hold as documents all the conversations that a user has. For a simple query, there is no index needed.

Upvotes: 1

Related Questions