Firestore query where map contains string

岁酱吖の 提交于 2021-01-04 12:34:49

问题


Data structure:

houses (collection)
  name (string)
  users (map)
    90c234jc23 (map)
      percentage: 100% (string/number)

Rules:

allow read: request.auth.uid in resource.data.users;

The problem is when I try to query houses which user owns:

FirebaseFirestore.getInstance().collection(House.COLLECTION)
//                .whereArrayContains(House.USERS_FIELD, currentUser.getUid()) // does not work
                .whereEqualTo("users." + currentUser.getUid(), currentUser.getUid()) // does not work either
                .get()

No result are returned.


回答1:


This query is not working because your users field is a map and not an array.

.whereArrayContains(House.USERS_FIELD, currentUser.getUid())

This query

.whereEqualTo("users." + currentUser.getUid(), currentUser.getUid())

is not working because your map value for users.<uid> is a string that says percentage: xx% and that statement is testing if percentage: xx% === <uid>, which is false.

And that strategy will be problematic since you can not do queries to find items that "are not null" or "strings not empty", etc.

I'm assuming that the percentage is the user's ownership in the house (?). If so, you might have better luck in trying to structure your house document data like this if you want to maintain the same structure of document as in your question

{
  name: "The Residence",
  users: {
    uid1: 80,
    uid2: 20
  }
}

That will allow you to do a query such as

.whereGreaterThan("users." + currentUser.getUid(), 0)

to find users that has some shares of ownership in that house.

But a fair bit of warning, as soon as you need composite indexes you will start having problems to maintain that structure. You might instead want to consider storing an array of users that owns that house for ease of querying.




回答2:


You cannot perform this type of query in firestore as there is no 'map-contains-key' operator. However, there are very simple workarounds for implementing this by making slight adjustments to your datastructure.

Specific Solution

Requirement: For this solution to work, each map value has to be uniquely identifyable in a firestore query, meaning it cannot be a map or an array.

If your case meets the listed requirements, you can go with @Dennis Alund's solution which suggests the following data structure:

{
  name: "The Residence",
  users: {
    uid1: 80,
    uid2: 20
  }
}

General Solution

If your map values are maps or arrays, you need to add a property to each value which will be constant across all created values of this type. Here is an example:

{
  name: "The Residence",
  users: {
    uid1: {
      exists: true,
      percentage: 80,
      ...
    },
    uid2:  {
      exists: true,
      percentage: 20,
      ...
    },
  }
}

Now you can simply use the query:

_firestore.collection('houses').whereEqualTo('users.<uid>.exists', true)


来源:https://stackoverflow.com/questions/54018158/firestore-query-where-map-contains-string

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!