firebase - 在 Firestore 中以“属于”和“拥有”的关系构建数据
问题描述
来自 SQL/Rails 背景,我有一个项目,我想使用 Firebase/Firestore(带有 React),并在设置数据和收集结构方面寻求帮助。
“楷模”:
- 用户
- 项目
- 类别
- 地点
一个用户可以拥有许多项目,一个项目属于一个用户。一个类别可以有许多项目,一个项目属于一个类别。
我需要能够在主页上显示所有类别、位置和项目。首先,我需要列出所有项目,它们可以按类别和/或位置进行过滤。
如何最好地在 Firestore 中设置这些数据?
对不起,rails 风格的解释,但 SQL 就在我的脑海里。
解决方案
我想您正在考虑外键,就像在 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 投影等等......)根据我的经验,第一个布局,更合适。
但是,这主要与应用程序设计和服务成本有关。
推荐阅读
- reactjs - 用 Jest 模拟一个 React 组件
- node.js - Knex 不会等待 sqlite 被释放
- javascript - 保存对话框中的 image.jpg 而不是 true.html
- ruby - 从 GitHub API 中删除多个文件
- api - 如何找到接受 oauth2 令牌的 API 端点
- identityserver4 - 按客户端分离用户存储
- javascript - Wordpress 中用于附属系统的 REST API
- c# - 带有 LDAP 身份验证的 Asp.Net Core 2.1 身份
- prestashop - 如何在 PrestaShop 中禁用电子邮件通知?
- laravel - 尝试发布到我的控制器时出现 419 错误