google firestore 上的链式查询
chained query on google firestore
我们的一个应用程序用例的数据以以下格式存储在 firestore 中:
"Collection" : "ROOT_COLLECTION"
"Documents" : MAIN_ID_1 : attribute : is_enabled:1
"subcollection": "Sessions"
Documents : Session_1: attribute: is_merged:false
Session_2: attribute: is_merged:true
Session_3: attribute: is_merged:false
MAIN_ID_2 : attribute : is_enabled:2
"subcollection": "Sessions"
Documents : Session_4: attribute: is_merged:false
Session_5: attribute: is_merged:true
Session_6: attribute: is_merged:true
MAIN_ID_3 : attribute : is_enabled:1
"subcollection": "Sessions"
Documents : Session_7: attribute: is_merged:true
Session_8: attribute: is_merged:true
Session_9: attribute: is_merged:true
MAIN_ID_4 : attribute : is_enabled:1
"subcollection": "Sessions"
Documents : Session_10: attribute: is_merged:false
Session_11: attribute: is_merged:false
......
这里我们想在单个查询中从根集合文档中找到所有 is_enabled 为真和 is_merged 为假的会话的所有最后一级会话,以便我们可以将侦听器放在顶部所有检索到的会话。
Query : is_enabled 在根集合中的文档上 : 1
is_merged 会话集合中的文档:false
Result 应该是会话文件:
会话 1、会话 3、会话 7、会话 8、会话 9
如何使用来自 firestore 的单个 chained/combined 查询和其上的侦听器来实现此目的?
我不会尝试使用这种结构来完成这项工作。这并不容易,而且有更好的方法。
您似乎陷入了将 Firestore 用作关系数据库而不是文档存储的陷阱。
如果您想保留此结构,那么我会建议添加一个云函数或在更新子集合中的会话时更新顶级文档的东西。这样你就可以在里面放一个像 contains_unmerged_session: Bool
之类的值。不过这感觉很老套。
一种可能更好的方法是拥有 sessions
的顶级集合,然后在每个会话中存储对会话文档中父项的引用。很难从你的问题中看出这种关系是如何运作的,但这可能是我会做的。
在 Firestore 中执行任何操作时,最好的方法是按照您希望在客户端上获取数据的方式构建数据。如果结构难以查询...更改结构。
查询只能针对单个集合或同名集合执行。查询只能考虑它们return文档中的数据,它们无法查看其他文档中的数据。
这两个限制相结合意味着您的用例无法作为当前数据模型上的单个查询来实现。
您的选择是:
- 或者先在顶级文档中查询
is_enabled
的正确值的文档,然后循环结果,并在其 sessions
中查询匹配 is_merged:false
的文档.
- 或者您可以将
is_enabled
中的数据复制到每个基础 sessions
文档中,然后使用 collection group query 跨所有 sessions
子集合执行查询。
两者都不是,如果这些比另一个更好。与往常一样,在处理 NoSQL 数据库时,您要在增加的数据存储和更复杂的数据模型之间进行权衡,以换取更快、更简单的查询。
我们的一个应用程序用例的数据以以下格式存储在 firestore 中:
"Collection" : "ROOT_COLLECTION"
"Documents" : MAIN_ID_1 : attribute : is_enabled:1
"subcollection": "Sessions"
Documents : Session_1: attribute: is_merged:false
Session_2: attribute: is_merged:true
Session_3: attribute: is_merged:false
MAIN_ID_2 : attribute : is_enabled:2
"subcollection": "Sessions"
Documents : Session_4: attribute: is_merged:false
Session_5: attribute: is_merged:true
Session_6: attribute: is_merged:true
MAIN_ID_3 : attribute : is_enabled:1
"subcollection": "Sessions"
Documents : Session_7: attribute: is_merged:true
Session_8: attribute: is_merged:true
Session_9: attribute: is_merged:true
MAIN_ID_4 : attribute : is_enabled:1
"subcollection": "Sessions"
Documents : Session_10: attribute: is_merged:false
Session_11: attribute: is_merged:false
......
这里我们想在单个查询中从根集合文档中找到所有 is_enabled 为真和 is_merged 为假的会话的所有最后一级会话,以便我们可以将侦听器放在顶部所有检索到的会话。
Query : is_enabled 在根集合中的文档上 : 1
is_merged 会话集合中的文档:false
Result 应该是会话文件: 会话 1、会话 3、会话 7、会话 8、会话 9
如何使用来自 firestore 的单个 chained/combined 查询和其上的侦听器来实现此目的?
我不会尝试使用这种结构来完成这项工作。这并不容易,而且有更好的方法。
您似乎陷入了将 Firestore 用作关系数据库而不是文档存储的陷阱。
如果您想保留此结构,那么我会建议添加一个云函数或在更新子集合中的会话时更新顶级文档的东西。这样你就可以在里面放一个像 contains_unmerged_session: Bool
之类的值。不过这感觉很老套。
一种可能更好的方法是拥有 sessions
的顶级集合,然后在每个会话中存储对会话文档中父项的引用。很难从你的问题中看出这种关系是如何运作的,但这可能是我会做的。
在 Firestore 中执行任何操作时,最好的方法是按照您希望在客户端上获取数据的方式构建数据。如果结构难以查询...更改结构。
查询只能针对单个集合或同名集合执行。查询只能考虑它们return文档中的数据,它们无法查看其他文档中的数据。
这两个限制相结合意味着您的用例无法作为当前数据模型上的单个查询来实现。
您的选择是:
- 或者先在顶级文档中查询
is_enabled
的正确值的文档,然后循环结果,并在其sessions
中查询匹配is_merged:false
的文档. - 或者您可以将
is_enabled
中的数据复制到每个基础sessions
文档中,然后使用 collection group query 跨所有sessions
子集合执行查询。
两者都不是,如果这些比另一个更好。与往常一样,在处理 NoSQL 数据库时,您要在增加的数据存储和更复杂的数据模型之间进行权衡,以换取更快、更简单的查询。