【问题标题】:How to structure data for orders in firestore?如何在firestore中为订单构建数据?
【发布时间】:2021-09-01 04:07:07
【问题描述】:
我正在制作一个送餐应用。在 order Id 中查询订单 status 的数据时,我遇到了障碍。
这是我的数据库设计:
Users (collections)
------> user id (documents)
----------> orders(object)
// Orders is a nested object. You can find an image of this down below.
orders{
"order_id":{
created_at: <time>
order_items: <array>
status: <string>
}
}
有什么方法可以让我收到待处理商品的订单状态?
这是数据库的图片
【问题讨论】:
标签:
firebase
react-native
google-cloud-firestore
【解决方案1】:
最好将orders 设为子集合(或单独的根级集合),这样您就可以查询具有特定状态的订单。数据库结构如下:
users -> {userId} -> orders -> {orderId}
(col) (doc) (col) (doc)
否则,在当前结构下,您必须使用 Javascript 获取完整的文档和排序顺序。另请注意,单个文档具有 1 MB limit,因此您限制了用户可以拥有的订单数量。
将每个订单移动到“订单”子集合中的文档后,您可以像这样查询挂单:
const q = query(collection(db, "users", userId, "orders"), where("status", "==", pending));
const querySnapshot = await getDocs(q);
querySnapshot.forEach((doc) => {
console.log(doc.id, " => ", doc.data());
});
【解决方案2】:
您的文档结构无法进行这样的查询。您必须获取文档,编写代码以从中提取订单,然后在应用程序的内存中过滤这些订单。
使用 Firestore,如果您尝试根据过滤条件查找某些项目的子集,则应将这些项目建模为集合中的单个文档,而不是全部一起在同一个文档中。这将允许您只选择您需要的项目。
对于所有关于建模数据的问题,最好的数据模型是满足查询需求的模型。在对数据进行建模之前,您应该先了解您的查询。
【解决方案3】:
正如@DougStevenson 在他的回答中提到的那样,您的实际文档结构不允许您使用查询获取所有挂单。
正如@Dharmaraj 在他的回答中提到的那样,一个可能的解决方案可能是将订单存储在一个集合中。但是,此解决方案的成本有点高,因为您必须为查询返回的每个文档支付文档读取费用。
请记住,将用户订单嵌套在文档中并没有错。我个人不会将订单嵌套在用户对象下的数组中,但我会创建一个单独的顶级集合和一个子集合。确实,单个文档中的数据限制为 1 MiB,但您可以通过将订单分片到多个文档中来重构数据库,如下所示:
Firestore-root
|
--- allOrders (collection)
|
--- $uid (document)
|
--- userOrders (collection)
|
--- 01-2021 (document) // month-year
|
--- orders (array)
|
--- #153108AB
|
--- createdAt: ...
|
--- order_items: ...
使用此结构,您将能够在一年中的每个月使用 1 MiB 的数据。我们现在谈论的是 12 MiB 的数据。这对于存储订单来说已经很多了。
如果您认为 12 MiB 的数据还不够,您可以考虑每天对订单进行分片,这意味着您将拥有 365 MiB,而不是 12 MiB 的数据.我可以向您保证,对于单个用户/年来说,这是足够的空间。现在,您所要做的就是下载文档并在客户端进行过滤。
想象一下 365 MiB 的数据可以容纳多少订单。如果您将它们添加到集合中,您愿意为每个文档支付阅读费用吗?
我前几天也写过一篇关于这个话题的文章,叫做: