我已将其中一个Cosmos DB的分区键设置为 /partition
.
例如:我们有一个包含订阅者列表的 Chat
文档,然后我们有 ChatMessages
包含文本,对作者的引用和其他一些属性 . 两个文档都有 partition
属性,其中包含类型'chat'和聊天ID .
Chat 示例:
{
"id" : "955f3eca-d28d-4f83-976a-f5ff26d0cf2c",
"name" : "SO questions",
"isChat" : true,
"partition" : "chat_955f3eca-d28d-4f83-976a-f5ff26d0cf2c",
"subscribers" : [
...
]
}
然后我们有 Message 这样的文件:
{
"id" : "4d1c7b8c-bf89-47e0-83e1-a8cf0d71ce5a",
"authorId" : "some guid",
"isMessage" : true,
"partition" : "chat_955f3eca-d28d-4f83-976a-f5ff26d0cf2c",
"text" : "What should I do?"
}
现在返回特定聊天的所有消息非常方便,我只需要使用属性 isMessage = true
查询分区 chat_955f3eca-d28d-4f83-976a-f5ff26d0cf2c
的所有文档 . 都好...
但是,如果我现在想通过id查询我的数据库中的特定消息,我通常只知道id,但不知道分区,因此必须运行慢 crosspartition
查询 . 然后,我引发了一个问题,即我是否应该将partitionKey添加到消息ID中,这样我就可以在查询数据库时拆分id以获得更快的查找速度 . 我看到文档的_rid属性看起来像是db的id和集合的id的组合,然后是文档特定的id . 我的意思是(简化):
Chat.Id = "abc"
Chat.Partition = "chat_abc" //[type]_[chatId]
Message.Id = "chat_abc|123" //[Chat.Partition]|[Message.Id]
Message.Partition = chat_abc //[Chat.Partition]
让我们假设我现在想通过 id
获取 Message
文档,我只是将 id
分割为 |
符号,然后查询文档,将 id
的第一部分作为分区,将完整的id作为密钥 .
那有意义吗?有没有更好的方法来做到这一点?我是否应该一直传递文件的 partitionKey
,而不仅仅是 id
?我应该只使用 _rid
属性吗?
任何经验都非常感谢!
UPDATE
我找到了以下答案here:
某些应用程序将分区密钥编码为ID的一部分,例如分区键是客户ID,ID =“customer_id.order_id”,因此您可以从ID值中提取分区键 .
我已经通过电子邮件进一步询问了宇宙团队,如果这是推荐的模式并发布答案,以防我得到任何答案 .
2 回答
是的,你提出从id中提取分区键的建议(通过像前缀/分隔符这样的约定)是有道理的 . 这在具有单个密钥并希望重构它以从其他存储系统使用Cosmos DB的应用程序中很常见 .
如果您是从头开始构建应用程序,则应考虑通过API /应用程序连接复合键(分区键项目键(“id”)) .
首先,如果您知道您的数据(和索引)大小)将保持在10gb限制内并且您的RU / sec限制是可以的,那么固定的无分区集合将绕过此问题 . 可能OP已经明确地决定需要进行分区,但是为了概括起见,这是一个需要注意的重要考虑因素 . 如果可能的话,KISS;)
如果必须进行分区,那么AFAIK除非你知道分区密钥,否则无法避免分割和开销 .
Imho OP建议将重复的分区键合并到id字段是一个相当丑陋的解决方案,因为:
Name id implies it is unique key ,分区键不是它的一部分,也不是此键及其唯一性所必需的 . 任何在上游使用此密钥的人都会产生更长密钥的强制超额成本,阻止使用更简单的
Guid
类型等 .将来你的_1786615会变得一团糟 .
合并的内部结构
id
would not be intuitive without documentation - 它正在进行's parts are not named and even if they look like to have a pattern new devs would not know for sure without finding external documentation to reliably understand what' .在语义层面上你的 data model does not require this 重复,它将是你的应用程序查询舒适,因此这样的黑客应该属于你的应用程序代码,而不是数据模型 . 如果可能,应避免这种泄漏问题 .
文档中的数据重复将不必要 increase document size, bandwidth 等(取决于规模和用法,可能是也可能不是值得注意的) . 有时需要文档内复制,但在这种情况下不一定是这样 .
更好的设计是 ensure the partition key is always present in logic context and could be passed along to lookups . 如果你没有它,那么也许你应该重构你的应用程序代码(而不是数据设计)来明确传递
chatId
以及需要的id
. 那是 WITHOUT 将它们合并为一些不透明的字符串格式 .另外,我没有看到使用
_rid
的好方法,就好像我没记错,它没有包含对分区或分区键的任何内部引用 .Disclaimer: 我对分区集合中的内部CosmosDB索引设计或
_rid
逻辑没有任何访问权或深入了解 . 我可能有误解了它是如何运作的 .