为多对多关系场景选择高效的数据模型Azure Cosmos Db



我正在尝试使用Azure cosmos数据库构建一个应用程序,要求存储针对用户的文章列表。在这种情况下,文章和用户将具有多对多映射。

  • 创建将通过我的应用程序公开的批量推送端点进行,该端点应该需要一篇文章和分配给它的用户列表。它还支持针对一篇文章删除相应的用户
  • 我还应该公开一个端点,它应该提供一个选项来获取针对用户的文章列表

解决上述两个问题我计划提供一个名为userArticles的容器,该容器的模式以user/id作为分区键,并将每篇文章作为一个单独的文档插入

{
id:guid
type:"article"
article: {
id:1
}
user: {
id: guid
}
}
{
id:guid
type:"article"
article: {
id:2
}
user: {
id: guid
}
}
  • 因此,我可以为传递到批量推送端点的每个用户ID批量插入一个文档。

  • 对于获取文章列表,因为我已经将分区键设置为user/id,这是一个点查询,可以解决我的性能问题。

  • 我可以看到,在我的情况下,我只能通过分区键删除文档,因为userId是分区键,我不能使用它,因为我需要单独删除特定的文章,不知道我如何在Cosmos中做到这一点?

注意:一篇文章可以拥有数百万用户但是一个用户可能只有几个100来阅读下面的文章我可以牺牲写性能,但不能牺牲读性能

有没有什么方法可以改变模型,使大容量插入/删除和读取消耗更少的Ru/s并获得更好的性能?。或者拆分模型会有所帮助?

这些问题在这里很难回答,因为NoSQL设计需要深入了解应用程序本身。我也不确定我是否遵循您的用例,但会尝试这种简单的方法。最有可能适合你的解决方案会更加微妙。

首先,要维护多对多关系,您需要两个容器。一个用于用户,一个用于文章。

为了设计用户的读取性能;许多";关系的另一面是,您可以将数组中的文章嵌入到每个用户文档中。但是您需要小心,因为文档的最大大小是2MB。此外,随着文章越来越大,它们的更新成本也会高得多,如果用户文档频繁更新,那么维护成本将高得令人望而却步。然后,解决方案是引用数据并将文章作为单独的行添加到用户容器中,/userId是添加文章的分区键。

你最终得到的是一个";用户";带有"/userId";分区键和用户文档以及多个文章文档。您需要消除用户和文章实体之间的歧义,因此您需要;类型";属性,值为"0";用户";或";文章";。为了获得用户和所有文档,您只需查询用户";从c中选择*,其中c.userId="用户a";。如果您只想要用户,请为"添加一个筛选器;type="用户a";。

还需要注意的是,您需要将文章所需的尽可能多的数据存储在用户容器中,以便在按用户查询时可以获得文章的所有属性。

为了保持数据同步,您需要使用Change Feed并监控文章容器,然后每当文章更新时,它就会向用户容器查询该文章id,然后就地更新每一篇文章。请注意,这两个查询都是跨分区的,可能会非常昂贵,而且您将更新同一篇文章的多个实例,因为您需要为每个用户复制它。但是,请记住,您这样做是因为您正在为用户的读取进行优化。

现在,如果你说有一个;数百万";文章和用户之间的关系,并且您希望对文章进行快速查询,则必须在文章容器中执行同样的操作。在这里,您肯定需要将用户添加为单独的行。但是您需要关注逻辑分区的大小。最大大小为20 GB。如果你接近这一点,或者如果articles:users之间的关系是无限的,那么你将需要一个具有更多基数的分区键。我不能告诉你这是什么,但它应该是你总是查询文章容器的依据,或者你也可以尝试对分区键值进行盐析;文章1_ 1"第1_ 2条";,等

同样的事情也适用于维护用户和文章之间的引用完整性。您需要使用ChangeFeed来监控用户容器,每当用户更新时,您都需要查询该用户的文章容器,并更新它的每个实例。

最新更新