简体   繁体   English

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

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

My objective:我的目标:

The web app (similar to Google Drive) has 2 screens.网络应用程序(类似于 Google Drive)有 2 个屏幕。

First screen is 'My Story' which displays all the story documents whom I'm the owner.第一个屏幕是“我的故事”,它显示我是所有者的所有故事文档。

Second screen is 'Shared with me' which displays all the story documents that I'm either reader, writer, or commenter.第二个屏幕是“与我共享”,它显示我是读者、作者或评论者的所有故事文档。

We have this /stories/{storyid}我们有这个/stories/{storyid}

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

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

Question: How to write the below query to fulfil the above objective?问题:如何编写以下查询来实现上述目标?

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

The above query does NOT work because it will require Firestore to index roles.alice, roles.bob, roles.david, roles.jane, and roles.[all_uid].上面的查询不起作用,因为它需要 Firestore 为roles.alice、roles.bob、roles.david、roles.jane 和roles.[all_uid] 建立索引。


Edit #1: Found a related post (with no answers) asking about Firestore querying with roles编辑 #1:找到了一个相关的帖子(没有答案)询问Firestore 使用角色查询

Now you can filter ...现在您可以过滤...

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

It will check if field orderDetails at property status equals to 'OPEN'它将检查属性状态的字段orderDetails是否等于“OPEN”

You cannot achieve this with your actual database structure in a way that you don't need to create an index for each user separately.您无法使用实际的数据库结构以不需要为每个用户分别创建索引的方式实现这一点。 To sovle this, you should duplicate your data.为了解决这个问题,你应该复制你的数据。 This practice is called denormalization and is a common practice when it comes to Firebase.这种做法称为denormalization ,是 Firebase 的常见做法。 If you are new to NoQSL databases, I recommend you see this video, Denormalization is normal with the Firebase Database for a better understanding.如果您不熟悉 NoQSL 数据库,我建议您观看此视频, Firebase 数据库的非规范化是正常的,以便更好地理解。 It is for Firebase realtime database but same rules apply to Cloud Firestore.它适用于 Firebase 实时数据库,但同样的规则适用于 Cloud Firestore。

Also, when you are duplicating data, there is one thing that need to keep in mind.此外,当您复制数据时,需要记住一件事。 In the same way you are adding data, you need to maintain it.与添加数据的方式相同,您需要维护它。 With other words, if you want to update/detele an item, you need to do it in every place that it exists.换句话说,如果你想更新/删除一个项目,你需要在它存在的每个地方都做。

That being said, you should create another collection named userStories , where you should add as documents all stories where a user is owner .话虽如此,您应该创建另一个名为userStories集合,您应该在其中添加用户为owner所有故事作为文档。 So you database structure should look similar to this:所以你的数据库结构应该类似于:

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

So a query like this:所以像这样的查询:

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

Will work perfectly fine.将工作得很好。

在此处输入图片说明 Please let me know if I'm mistaken, but it appears that your query should actually work.如果我弄错了,请告诉我,但您的查询似乎确实有效。 as an experiment I added the structure you gave in the question and performed the query successfully in the firebase console.作为实验,我添加了您在问题中给出的结构,并在 firebase 控制台中成功执行了查询。

Is this not what you are going for?这不是你想要的吗? I also made sure that the "in" operator works for this case as well.我还确保“in”运算符也适用于这种情况。 In this way you could ask which stories the user is owner & commenter.通过这种方式,您可以询问用户是所有者和评论者的哪些故事。

在此处输入图片说明

This pulls in the correct results:这会产生正确的结果: 在此处输入图片说明

It is not possible therefore we need to duplicate data in NoSQL.这是不可能的,因此我们需要在 NoSQL 中复制数据。

One possible data structure is一种可能的数据结构是

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

So we can query for the web app UI 'My Story'因此我们可以查询 Web 应用程序 UI 'My Story'

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

While we can query for the web app UI of 'Shared with me'虽然我们可以查询“与我共享”的网络应用程序 UI

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

Answer is inspired by @Doug Stevenson comments.答案的灵感来自@Doug Stevenson 评论。

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

相关问题 在 Flutter 中的嵌套集合中查询 Firestore 文档 - Query Firestore documents inside a nested collection in Flutter Firestore:如何查询文档子集中的角色映射? - Firestore: How to query a map of roles inside a subcollection of documents? 如何将我的 Firestore 集合文档映射到表格中 - How to map my firestore collection documents into a table 如何查询集合中的多个文档(Firestore/Flutter) - How to query through multiple documents in a collection (Firestore/Flutter) 如何在Firestore集合中查询其值包含在列表中的文档 - How to query Firestore collection for documents with field whose value is contained in a list 按对象查询Firestore集合 - Query Firestore collection by object Cloud Firestore:如何在我的集合查询中获取文档引用并将其映射为 JSON 值? - Cloud Firestore: how to fetch a document reference inside my collection query and map it as a JSON value? Firestore:按对象的属性查询文档 - Firestore: Query documents by property of object 查询Firestore集合中的所有文档而不进行循环 - Query all Documents in a Firestore Collection without Looping 如何将具有值的集合中的所有文档以 map firestore web 的形式推送到另一个集合 - How to push all the documents in a collection with values to another collection in form of map firestore web
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM