以属于和多对关系的方式构建 Firestore 中的数据

Chr*_*ger 2 firebase react-native google-cloud-firestore

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

“楷模”:

  • 用户
  • 项目
  • 类别
  • 地点

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

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

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

抱歉我用的是 Rails 风格的解释,但我脑子里全是 SQL。

mat*_*ati 6

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

对此没有具体的食谱。

Alex 试图说明的是,你应该考虑哪个是你设计中的核心元素。看来这是“item”元素。

一种可能的设计可能是:

  • 将类别和位置以简单形式存储到表示您的项目的 json 对象中。

  • 然后用一个数组来列出前端的item

  • 最后在前端使用 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...*/},
        /*...*/
    ]
}

Run Code Online (Sandbox Code Playgroud)

而不是:

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"
}
Run Code Online (Sandbox Code Playgroud)

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

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

如果满足以下条件,则前者效果很好:

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

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

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