首页 文章

将PartitionKey编码为文档ID?

提问于
浏览
0

我已将其中一个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 回答

  • 0

    是的,你提出从id中提取分区键的建议(通过像前缀/分隔符这样的约定)是有道理的 . 这在具有单个密钥并希望重构它以从其他存储系统使用Cosmos DB的应用程序中很常见 .

    如果您是从头开始构建应用程序,则应考虑通过API /应用程序连接复合键(分区键项目键(“id”)) .

  • 1

    首先,如果您知道您的数据(和索引)大小)将保持在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 逻辑没有任何访问权或深入了解 . 我可能有误解了它是如何运作的 .

相关问题