如何根据主集合的字段和云 Firestore 中的子集合的字段从子集合中查询文档?

问题描述

我是 Firebase Cloud Firestore 的新手,需要帮助理解一下。

我正在从事以下结构的项目。

firebase firestore collection screenshot

firebase firestore subcollection screenshot

每个“餐厅”文档都包含自己的“产品”子集合。

在这里,我想运行一个查询以按不同的方式获取所有产品 包含“咖啡”标签且位于特定区域的餐厅 密码“234144”。

我尝试通过向特定餐厅拥有的每个产品添加 Pincode 来尝试集合组查询,但更改 Pincode 会花费很多,因为我猜所有产品都必须进行编辑。

是否有任何有效的方法可以做到这一点,或者在这方面是不可能的 以有效的方式使用数据库

请告诉我您的想法...谢谢。

解决方法

如果我理解正确,您想检索具有特定标签和密码的所有产品(我认为这类似于邮政编码?)。我真的只有两种选择:

集合组查询

正如您所提到的,您可以将 tagpincode 存储在 product 文档中。然后沿着这些行执行单个集合组查询(原谅 javascript,但我不熟悉 Dart,它应该非常相似):

var products = await firestore.collectionGroup('products')
                       .where('tag','==','coffee')
                       .where('pincode','234144').get();

正如您所指出的,使用此解决方案您需要在每个产品中保留pincode 这段数据是重复的,感觉应该避免它是正常的因为它既浪费又危险(可能会不同步),但这是要走的路!这称为非规范化。这在 this video by Todd Kerpelman 中有很好的解释。
然后,您可以创建一个由 restaurant 更新触发的云函数,以使 products 中的 pincode 与相应的 pincode 保持同步在餐厅

先查询餐厅,再查询产品

要仅保留餐厅中的pincode,您必须分两步进行查询:首先过滤特定密码中的餐厅,然后按标签过滤产品:

// 1 - retrieve restaurants in specific pincode
var restaurants = await firestore.collection('restaurants').where('pincode','234144').get();

// 2 - For each retrieved restaurant,retrieve all products matching the tag
var products = [];
for(let i = 0; i < restaurants.docs.length; ++i) {
  var p = await restaurants.docs[i].collection("products").where("tag","==","coffee");
  products.push(p);
}

使用此方法,无需在每个产品中重复pincode,但是您的查询不太理想,因为您加载了可能无用的餐厅不在您的密码中提供咖啡。