如何构建 DocumentDB 数据库
How to structure a DocumentDB Database
我对 NoSQL 完全陌生,所以我可能只是有一个基本的误解...
我浏览了 this tutorial,其中介绍了如何使用 Firebase 制作聊天应用程序。例如,直接消息聊天的 JSON 如下所示:
{
"userMessages": {
"userid1": {
"userid2": {
"messageId1": {
"uid": "userid1",
"body": "Hello!",
"timestamp": firebase.database.ServerValue.TIMESTAMP
},
"messageId2": {
"uid": "userid2",
"body": "Hey!",
"timestamp": firebase.database.ServerValue.TIMESTAMP
}
}
}
}
}
请求消息时,您会查看 userMessages/UserId1/UserId2。这将给出两个用户之间的所有消息。
我决定尝试使用 DocumentDB 进行类似的操作,但我不确定该怎么做。似乎我应该能够创建一个名为 UserMessages 的容器并将所有数据放入上面,但似乎 DocumentDB 只允许检索和更新顶级文档。所以在这种情况下,我需要获取 userid1 下的所有内容,并且每当我添加消息时,我都需要更新整个 userid1 文档,包括所有未更改的消息。
我认为使这项工作可行的唯一方法是展平该设计。但是扁平化应用程序的其余部分(包含许多更复杂的对象)似乎需要创建更多的容器(每个容器都要花钱),而我应该能够拥有更多的分层设计并仅更新我需要的层或只推送需要推送的额外数据。
长话短说,我是否对 NoSQL 的结构存在根本性的误解,或者 DocumentDB 与其他 NoSQL 解决方案的区别如此之大?谢谢!
DocDB 中的文档存储在集合 中。集合可以包含任何类型(无模式)的文档,并且是计费单位。 (参见Hierarchical model here)。
当您说您需要更新整个文档时,您对 DocDB 的看法是正确的,您不能进行部分更新,因此在您原来的方法中,每次新消息到达时都会变成一个较慢的过程。
但是您可以重构较小文档的设计,并且仍然可以使用类似以下内容查询 user1 / user2 关系:
{
"type":"message",
"from":"userid1",
"to":"userid2",
"conversation":"userid1-userid2",
"body":"Hello!":
"timestamp":firebase.database.ServerValue.TIMESTAMP
}
{
"type":"message",
"from":"userid2",
"to":"userid1",
"conversation":"userid1-userid2",
"body":"Hey!":
"timestamp":firebase.database.ServerValue.TIMESTAMP
}
因此您实际上可以执行 2 个不同的查询:
- 通过
conversation
属性查询user1和user2的对话是什么
- 哪些消息是由 user1 发送给 user2(或仅由 user1 发送)的
from
和 to
属性。您可以使用 from
查询 user1 发送给任何用户的消息,或者使用 to
. 接收的消息
如果您阅读 how the internal indexes are managed,您会发现所有属性都会自动建立索引,并且像这样展平数据时不会出现性能问题。
我不熟悉 Firebase,如果应用程序需要第一种格式的信息,您可能需要更改一些代码(可能需要创建一些翻译中间件)。
希望对您有所帮助!
我对 NoSQL 完全陌生,所以我可能只是有一个基本的误解...
我浏览了 this tutorial,其中介绍了如何使用 Firebase 制作聊天应用程序。例如,直接消息聊天的 JSON 如下所示:
{
"userMessages": {
"userid1": {
"userid2": {
"messageId1": {
"uid": "userid1",
"body": "Hello!",
"timestamp": firebase.database.ServerValue.TIMESTAMP
},
"messageId2": {
"uid": "userid2",
"body": "Hey!",
"timestamp": firebase.database.ServerValue.TIMESTAMP
}
}
}
}
}
请求消息时,您会查看 userMessages/UserId1/UserId2。这将给出两个用户之间的所有消息。
我决定尝试使用 DocumentDB 进行类似的操作,但我不确定该怎么做。似乎我应该能够创建一个名为 UserMessages 的容器并将所有数据放入上面,但似乎 DocumentDB 只允许检索和更新顶级文档。所以在这种情况下,我需要获取 userid1 下的所有内容,并且每当我添加消息时,我都需要更新整个 userid1 文档,包括所有未更改的消息。
我认为使这项工作可行的唯一方法是展平该设计。但是扁平化应用程序的其余部分(包含许多更复杂的对象)似乎需要创建更多的容器(每个容器都要花钱),而我应该能够拥有更多的分层设计并仅更新我需要的层或只推送需要推送的额外数据。
长话短说,我是否对 NoSQL 的结构存在根本性的误解,或者 DocumentDB 与其他 NoSQL 解决方案的区别如此之大?谢谢!
DocDB 中的文档存储在集合 中。集合可以包含任何类型(无模式)的文档,并且是计费单位。 (参见Hierarchical model here)。
当您说您需要更新整个文档时,您对 DocDB 的看法是正确的,您不能进行部分更新,因此在您原来的方法中,每次新消息到达时都会变成一个较慢的过程。
但是您可以重构较小文档的设计,并且仍然可以使用类似以下内容查询 user1 / user2 关系:
{
"type":"message",
"from":"userid1",
"to":"userid2",
"conversation":"userid1-userid2",
"body":"Hello!":
"timestamp":firebase.database.ServerValue.TIMESTAMP
}
{
"type":"message",
"from":"userid2",
"to":"userid1",
"conversation":"userid1-userid2",
"body":"Hey!":
"timestamp":firebase.database.ServerValue.TIMESTAMP
}
因此您实际上可以执行 2 个不同的查询:
- 通过
conversation
属性查询user1和user2的对话是什么 - 哪些消息是由 user1 发送给 user2(或仅由 user1 发送)的
from
和to
属性。您可以使用from
查询 user1 发送给任何用户的消息,或者使用to
. 接收的消息
如果您阅读 how the internal indexes are managed,您会发现所有属性都会自动建立索引,并且像这样展平数据时不会出现性能问题。
我不熟悉 Firebase,如果应用程序需要第一种格式的信息,您可能需要更改一些代码(可能需要创建一些翻译中间件)。
希望对您有所帮助!