繁体   English   中英

Firestore:如何查询文档集合中的地图对象?

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

我的目标:

网络应用程序(类似于 Google Drive)有 2 个屏幕。

第一个屏幕是“我的故事”,它显示我是所有者的所有故事文档。

第二个屏幕是“与我共享”,它显示我是读者、作者或评论者的所有故事文档。

我们有这个/stories/{storyid}

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

完整的数据结构参考: https : //firebase.google.com/docs/firestore/solutions/role-based-access

问题:如何编写以下查询来实现上述目标?

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

上面的查询不起作用,因为它需要 Firestore 为roles.alice、roles.bob、roles.david、roles.jane 和roles.[all_uid] 建立索引。


编辑 #1:找到了一个相关的帖子(没有答案)询问Firestore 使用角色查询

现在您可以过滤...

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

它将检查属性状态的字段orderDetails是否等于“OPEN”

您无法使用实际的数据库结构以不需要为每个用户分别创建索引的方式实现这一点。 为了解决这个问题,你应该复制你的数据。 这种做法称为denormalization ,是 Firebase 的常见做法。 如果您不熟悉 NoQSL 数据库,我建议您观看此视频, Firebase 数据库的非规范化是正常的,以便更好地理解。 它适用于 Firebase 实时数据库,但同样的规则适用于 Cloud Firestore。

此外,当您复制数据时,需要记住一件事。 与添加数据的方式相同,您需要维护它。 换句话说,如果你想更新/删除一个项目,你需要在它存在的每个地方都做。

话虽如此,您应该创建另一个名为userStories集合,您应该在其中添加用户为owner所有故事作为文档。 所以你的数据库结构应该类似于:

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

所以像这样的查询:

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

将工作得很好。

在此处输入图片说明 如果我弄错了,请告诉我,但您的查询似乎确实有效。 作为实验,我添加了您在问题中给出的结构,并在 firebase 控制台中成功执行了查询。

这不是你想要的吗? 我还确保“in”运算符也适用于这种情况。 通过这种方式,您可以询问用户是所有者和评论者的哪些故事。

在此处输入图片说明

这会产生正确的结果: 在此处输入图片说明

这是不可能的,因此我们需要在 NoSQL 中复制数据。

一种可能的数据结构是

/故事/{故事ID}

{
  title: "A Great Story",
  content: "Once upon a time ...",
  roles: {
    alice: "owner",
    bob: "reader",
    david: "writer",
    jane: "commenter",
    mary: "writer",
    // ...
  },
  owner: "alice", // newly added
  shared: ["bob", "david", "jane", "mary"] // newly added
  // alice, bob, david, jane, mary are firebase auth uid
}

因此我们可以查询 Web 应用程序 UI 'My Story'

db
.collection('stories')
.where('owner', '==', uid)

虽然我们可以查询“与我共享”的网络应用程序 UI

db
.collection('stories')
.where('shared', 'array_contains', uid)

答案的灵感来自@Doug Stevenson 评论。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM