目前,我的Firestore查询技术存在一些问题。根据我最近发布的这个stackoverflow帖子,Querying with two array with firestore security rules
答案是建议将“id”添加到对象中,并以键作为id,而值仅是“true”。我已经完成了这一步,现在我的结构如下所示:
javascript - 在Firestore中查询对象 key-LMLPHP
这让我有了这个查询:

db.collection('Depots')
  .where(`products.${productId}`, '==', true)
  .where(`users.${userId}`, '==', true)
  .where('created', '>', 1585998560500)
  .orderBy('created', 'asc')
  .get();
该查询使我抛出错误,要求创建索引:

但是,这会尝试索引特定的对象键,即QXooVYGBIFWKo6C这样products.QXooVYGBIFWKo6C。从本质上讲,这不是我想要的,因为此查询会发生变化,并且可能具有无限的可能性,这意味着我必须为每个键条目创建另一个索引才能查询它。
有什么办法解决这个问题?由于查询中使用的运算符不同,我假设它需要为该查询建立索引,因此我想知道是否存在针对此问题的解决方法。
提前非常感谢您。

最佳答案

在聊天中讨论之后,这是我建议的起点。谁知道最终架构会是什么样子,但我认为这一点或与之非常接近。您说一个用户可以同时存在于多个软件仓库中,并且多个软件仓库可以同时包含相同的产品。您还说过,一个仓库在给定时间永远不能拥有40个以上的用户,因此40个用户的阵列肯定不会侵犯Firestore的1,048,576字节的文档限制。

[collection]
    <documentId>
        - field: value

[depots]

    <UUID>
        - depotId: string       "depot456"
        - productCount: num     5,000

    <UUID>
        - depotId: string       "depot789"
        - productCount: num     4,500


[products]

    <UUID>
        - productId: string     "lotion123"
        - depotId: string       "depot456"
        - users: [string]       ["user10", "user27", "user33"]

    <UUID>
        - productId: string     "lotion123"
        - depotId: string       "depot789"
        - users: [string]       ["user10", "user17", "user50"]


[users]

    <userId>
        - depots: [string]      ["depot456", "depot999"]

    <userId>
        - depots: [string]      ["depot333", "depot999"]

在NoSQL中,存储很便宜,并且计算并不会使您的数据非正常化,从而不会使查询变得可能和高效(快速又便宜)。

要在单个查询中查找user10lotion123都为true的所有软件仓库,请查询productId等于xusers数组包含y的产品集合,并从这些结果中收集depotId值。如果要保留数组包含的其他操作,则必须进一步对数据进行规范化(将数组替换为单个用户)。或者,您可以将此查询分为两个单独的查询。

使用此模型,当用户离开仓库时,获取users数组包含该用户的所有产品,然后从数组中删除该userId。当用户加入软件仓库时,获取depotId等于x的所有产品,并将该userId附加到数组中。

观看此视频以及Rick的其他视频,以牢固地掌握NoSQL:https://www.youtube.com/watch?v=HaEPXoXVf2k

07-24 09:44
查看更多