首页 > 解决方案 > 在 Firestore 中以“属于”和“拥有”的关系构建数据

问题描述

来自 SQL/Rails 背景,我有一个项目,我想使用 Firebase/Firestore(带有 React),并在设置数据和收集结构方面寻求帮助。

“楷模”:

一个用户可以拥有许多项目,一个项目属于一个用户。一个类别可以有许多项目,一个项目属于一个类别。

我需要能够在主页上显示所有类别、位置和项目。首先,我需要列出所有项目,它们可以按类别和/或位置进行过滤。

如何最好地在 Firestore 中设置这些数据?

对不起,rails 风格的解释,但 SQL 就在我的脑海里。

标签: firebasereact-nativegoogle-cloud-firestore

解决方案


您正在考虑外键,就像在 sql DB 中一样。在 nosql 场景中通常发生的情况是,您应该避免关系,而是将关系扁平化为“大”文档(nosql 中的 document=json 对象)。

没有具体的食谱。

亚历克斯试图解释的是你应该考虑哪个是你设计的核心元素。这似乎是“项目”元素。

一个可能的设计可能是:

  • 将类别和位置直接存储到代表您的项目的 json 对象中。

  • 然后使用数组列出前端的项目

  • 最后使用前端的 JS array.filter() 函数来过滤响应用户操作时显示的内容。

如果您只需要显示属于某个用户的项目,请在“项目”文档中添加一个“用户”字段,并要求 Firestore 仅返回那些“用户”字段与您登录的用户匹配的文档。

这有点过时了,但应该可以帮助您了解 nosql 中的数据非规范化: https ://firebase.googleblog.com/2013/04/denormalizing-your-data-is-normal.html?m=1

编辑

参考 Jay 的回答和评论中指出的 MongoDB 文章,我一直在努力做出决定:是嵌入数据还是引用它,但我总是最终嵌入小文档。

杰伊能分享你的经验吗?

我总是觉得在前端创建额外的查询以重新加入所需的信息(a-la sql)很无聊,而我很少在指向其他文档方面有优势。我想这主要取决于应用程序设计。

简而言之

我更喜欢类似的东西

users_collection > user_uuid_0
{
    "name": "John"
    "items": [
        {/*...plain item1 object here...*/},
        {/*...plain item2 object here...*/},
        /*...*/
    ]
}

而不是:

users_collection > user_uuid_0
{
    "name": "John"
    "items_ids":[
      "item_uuid_0",
      "item_uuid_1",
      /*...*/
    ]
}

---

items_collection > item_1
{
   /*all item fields*/
   "belong_to": "user_uuid_0"
}

items_collection > item_2
{
   /*all item fields*/
   "belong_to": "user_uuid_0"
}

后一种解决方案的好处是更灵活和解耦:您可以更改用户详细信息而不会对项目产生任何影响,并且您的有效负载更小(如果流量大小比服务中的操作数更重要)。

缺点是:需要对数据库进行 2 次查询(1 次获取用户文档,1 次获取由 id 过滤的项目),而只需 1 次;它需要在前端进行许多操作才能重新收集所有内容,而无需添加任何操作,因为文档的先前布局已经嵌入了所有内容。

前者在以下情况下效果很好:

  • 你有一对少的关系(一对多倾向于像 Jay 建议的那样使用 uuid refs)
  • 你的文件很小(否则杰的解决方案会更好)
  • 如果您按操作而不是流量大小计费

当我们考虑像 firestore 这样的托管 nosql 数据库时,通常情况下,您的 CRUD API 基本上是一个 REST api 或非常接近它的东西(没有 JPA、DTO 投影等等......)根据我的经验,第一个布局,更合适。

但是,这主要与应用程序设计和服务成本有关。


推荐阅读