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

时间:2019-02-21 16:01:22

标签: firebase google-cloud-firestore angularfire2 angularfire5

我的目标:

该网络应用程序(类似于Google云端硬盘)有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索引role.alice,roles.bob,roles.david,roles.jane和role。[all_uid]。


编辑#1:找到一则相关帖子(无答案),询问Firestore querying with roles

4 个答案:

答案 0 :(得分:3)

现在您可以过滤...

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

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

答案 1 :(得分:2)

您无法通过实际的数据库结构来实现此目的,而不必为每个用户分别创建索引。要解决这个问题,您应该复制数据。这种做法称为 @AfterSuite public void generateReport() { File reportOutputDirectory = new File("target"); // List<String> jsonFiles = new ArrayList<String>(); jsonFiles.add("target/cucumber.json"); String projectName = "Your Sample Project Name"; String buildNumber = "1.0"; Configuration configuration = new Configuration(reportOutputDirectory, projectName); configuration.setRunWithJenkins(true); configuration.setBuildNumber(buildNumber); ReportBuilder reportBuilder = new ReportBuilder(jsonFiles, configuration); reportBuilder.generateReports(); } ,是Firebase的常见做法。如果您不熟悉NoQSL数据库,建议您观看此视频Denormalization is normal with the Firebase Database,以更好地理解。它用于Firebase实时数据库,但相同的规则适用于Cloud Firestore。

此外,在复制数据时,需要记住一件事。用与添加数据相同的方式,您需要对其进行维护。换句话说,如果您想更新/删除项目,则需要在它存在的每个位置进行。

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

owner

这样的查询:

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

可以很好地工作。

答案 2 :(得分:2)

enter image description here如果我输入错了,请告诉我,但看来您的查询应该可以正常工作。作为实验,我添加了您在问题中给出的结构,并在firebase控制台中成功执行了查询。

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

enter image description here

这将得出正确的结果: enter image description here

答案 3 :(得分:0)

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

一种可能的数据结构是

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

因此我们可以查询Web应用程序UI“我的故事”

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

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

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

答案受到@Doug Stevenson评论的启发。