【问题标题】:Firestore: how to filter documents by existing in other collection?Firestore:如何通过存在于其他集合中来过滤文档?
【发布时间】:2021-12-23 20:24:38
【问题描述】:

例如,我想获取属于某个“空间”成员的所有用户。

简化的 Firestore 规则示例:

match /users/{userId} {
  allow read: if exists(/databases/$(database)/documents/spaces/SPACEID/members/$(userId));
}

网站中的JS代码:

firebaseApp
    .firestore()
    .collection("users")
    .where( ??? )
    .onSnapshot((querySnapshot) => {
        ...
    });

我只能提出 2 个工作选项:

  1. /users 集合中创建spacesArray 字段并使用usersRef.where("spacesArray", "array-contains", "SPACEID")。但在这种情况下,任何人都可以通过阅读spacesArray 找出用​​户所在的组。此外,问题在于这些数组可能非常大,而客户端不需要这些数据,这会导致流量过多。
  2. 先获取空间中的所有成员列表/databases/$(database)/documents/spaces/SPACEID/members/,然后逐个获取每个用户。这个选项的问题是可能有很多用户,每次刷新页面都会通过.get().onSnapshot()请求成百上千个用户,这是多余的。

理想的选择是使用where 字段中规则中的exists(...) 方法的类似物,或者出于保密目的以某种方式从用户文档中过滤掉spacesArray

【问题讨论】:

    标签: javascript node.js firebase google-cloud-firestore


    【解决方案1】:

    Firestore 查询只能对属于查询返回的文档的一部分的数据进行排序/过滤。无法对另一个文档/集合中的信息进行排序/过滤。

    因此,您在安全规则中的 exists 检查通常非常适合获取单个文档(在更多 granular security rules 语法中称为 get),但不适用于处理批量读取(在粒度安全中称为 list规则)。

    如果您考虑用户私人信息的空间列表,请考虑将其存储在 UserSpaces 集合中,这(正如您在 #2 中所说)会导致更多读取,或者考虑仅存储公共数组中的空间。

    【讨论】:

      猜你喜欢
      • 2020-07-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-14
      • 1970-01-01
      相关资源
      最近更新 更多