2017-07-21 159 views
1

我是使用DocumentDB API的Azure Cosmos DB的新手。我计划对我的数据建模,以便一个文档引用另一个文档。这很简单,如Modeling document data中所述。不过,我也想将相关文件分成不同的集合(这个决定与数据是如何相互关联的partitioned)。Cosmos DB:如何使用DocumentDB API在单独的集合中引用文档

编辑2017/7/24:为了回应一个疑问,为什么我选择使用单独的集合:单独集合的推理主要归结为分区键和读/写优先级。由于需要在集合中的所有文档中都存在某个分区键,因此分离所选分区键不属于的文档是有意义的。在对选项进行了大量权衡之后,我决定使用的分区键是一种可以优化写入速度并在分片间均匀分配数据的分区键 - 但不幸的是,它并不属于我的“元数据”文档。由于元数据和测量数据之间存在着巨大的关系,我选择在测量中使用对元数据的引用,而不是嵌入。而且由于元数据很少(或绝对不会)被附加到每个度量上,所以我认为额外往返DB的费用是一个非常低的问题。

由于引用是未经数据库验证的“薄弱环节”,因此存储附加信息(如集合名称)是否可能并明智?也就是说,我们可以使用一种路径而不是只有一个字符串ID?

Metadata document in collection "Metadata": 
{ 
    "id": "metadata1", 
    ... 
} 

Measurement document in collection "Measurements": 
{ 
    "id": "measurement1", 
    "metadata-id" : "../Metadata/metadata1", 
    ... 
} 

然后,当我解析我的应用程序/脚本中的数据时,我知道要查询什么集合和文档。最后,我认为还有其他更好的方法可以解决这个问题,我欢迎你的建议(例如下划线,而不是斜线;使用符号表示集合,例如$元数据等)。或者,我使用关系跨越集合的代码味道?

谢谢!

编辑:对于downvoter,你能解释你的推理吗?我的问题是不明白的,不清楚的,还是没有用的?为什么?

+0

你能否详细说明你的分区是什么让你认为需要另一个集合是必要的?我一直在广泛使用宇宙一段时间,从来没有发现这种情况。 (不是downvoter btw它的一个公平的问题)只是好奇你的推理。 –

+0

@JesseCarter我更新了我的问题,阐述了我使用单独集合的理由。我很好奇你如何能够在优化读/写速度的同时使用单个分区密钥来实现异构(假设)数据? – brudert

+0

请参阅我提供的关于如何使用单个集合完成要查找的内容的答案。你正在考虑一种危险和不必要的方式,即每种类型需要一个集合。情况并非如此,因为集合是通用存储而不是实体特定的表。考虑到开始添加第三种或第四种实体类型时的成本差异,并且必须为每增加一个新的实体类型付费。 –

回答

2

你在想这个错误的方式和承担显著更多的成本“优化”,因为你每在计费是没有必要的收集水平。你应该做的是选择一个更通用的分区密钥。类似于keypartitionKey。这里的折衷是,您需要确保在您的客户端应用程序中,您在所有文档中填充此属性(这可能会导致重复值,但最终没关系)。他们可以继续使用您最初选择的用于测量文档的值,并为元数据文档设置不同的值。

我在这里已经写了一些其他答案,并且我认为这是关于有效和大规模使用Cosmos的最大误解之一。在许多Cosmos的例子中,他们谈论如何选择一个分区键,如deviceIdpostal code,这意味着你正在处理同类文档。

请参考我回答的关于homogeneous vs heterogeneous in documentdb的这个问题。这种模式的最大理由是在Cosmos中添加了Graph API,这使得必须在单个集合中有许多不同的实体types,并且完全支持您正在描述的用例减去额外的集合。很明显,在处理异构类型时,不会在所有文档中出现适合分区键的单个属性,这就是为什么您需要使用通用属性。

+0

这很好。这只是一个轻微的范式转变,但我认为这将与我计划如何构建数据的方式一致。我正在考虑属于不同集合的文档将被合并为一个集合,并增加一个新的分区键作为“集合”(或“partitionKey”,或其他)。所以每个文档都有两个键来帮助提供上下文:“集合”和“类型”。谢啦!我相信我的老板也很感激! – brudert

+0

@brudert没问题!我很高兴你发现它有帮助。我一直有意将一些博客文章放在一起,目的是为了更好地向人们提供文档/解释,因为目前关于最佳实践的信息并不多。如果您满意,请随时接受这个答案 –

1

你想要做的是可行的。您使用的惯例不是特别重要,只要您能够找出参考。请记住,使用这种类型的“关系”会很慢,因为您需要从一个集合中获取所有文档,然后在单独的查询中获取相关文档。它可能会对您的应用程序造成严重影响。

另一种可能性是优化您的数据以供阅读:您可以将元数据文档嵌入到其他文档中。你的数据将被复制,所以如果你更新这些文件,你将不得不在两个集合中更新它们,但是你可能会比你阅读的时间少(可能,如果情况并非如此,这种设置会更糟)。

你的文件应该是这样的:

Metadata document in collection "Metadata": 
{ 
    "id": "metadata1", 
    ... 
} 

Measurement document in collection "Measurements": 
{ 
    "id": "measurement1", 
    "metadata" : { 
     "id": "metadata1", 
     ... 
    }, 
    ... 
} 
+0

我很欣赏这些反馈!我知道读取速度会很慢,但这不应该成为我的用户关注的问题。实际上,数百万次的测量结果将被下载,而元数据很少。当下载元数据时,对于每种类型的度量可能只需要一次,而不是附加到每个度量(使用某些逻辑来计算独特的元数据文件等)。 – brudert

+0

我考虑过嵌入元数据。由于每次测量都不是必需的,并且数据量相当大,所以我更愿意将它们归一化。 – brudert

相关问题