10

我的目标:

网络应用程序(类似于 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 查询角色

4

4 回答 4

9

现在您可以过滤...

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

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

于 2020-07-29T14:42:57.197 回答
8

您无法以不需要为每个用户分别创建索引的方式使用实际的数据库结构来实现这一点。为了解决这个问题,您应该复制您的数据。这种做法称为denormalizationFirebase 的常见做法。如果您是 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');

将工作得很好。

于 2019-02-21T17:16:31.840 回答
3

在此处输入图像描述如果我弄错了,请告诉我,但您的查询似乎应该有效。作为实验,我添加了您在问题中提供的结构,并在 firebase 控制台中成功执行了查询。

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

在此处输入图像描述

这会得出正确的结果: 在此处输入图像描述

于 2020-03-03T22:38:35.443 回答
0

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

一种可能的数据结构是

/故事/{storyid}

{
  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
}

所以我们可以查询网络应用程序 UI '我的故事'

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

虽然我们可以查询“与我共享”的 Web 应用 UI

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

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

于 2019-02-21T17:48:25.723 回答