mongodb - 如何处理MongoDB中的多对多关系?

标签 mongodb mongoose schema entity-relationship

我对 MongoDB 中的多对多关系实现有一个特定的问题。

I have collections of Songs and Artists(Millions document). Here the song can be sung by Many Artists and an artist can sing Many songs. So I followed the approach of Document referencing in both collections. like this...

1. 歌曲合集:-

{
  _id:ObjectId("dge547567hheheasfw3454dfg"),
   title:"xyz",
   artists:[ObjectId("xfvdg464654"), ...] //many artists // artists ids
}

2. 艺术家收藏:-

{
  _id:ObjectId("dge547567hheheasfw3454dfg"),
   title:"xyz",
   songs:[ObjectId("xfvdg464654"), ...] //many songs // songs Ids 
}

But here the problem is while deleting artist I have to delete an artist from an array of the artist in all document of the song which has an artist and vice versa. Which can cause the problem of Atomicity. How can I ensure atomicity here?

Secondly when the database will grow and songs are sung by the artist will increase thus resulting document growth of both collection and document size can reach to 16MB or greater(MAX DOC SIZE).

那么在这种情况下可以做些什么呢?

最佳答案

让我们从为您的案例详细说明我们的多对多关系开始,并尝试了解可以做什么和不可以做什么 -

  • 一首歌可以由多达 10 位或 20 位艺术家演唱(假设它并不复杂/多样化,可能需要 100 位艺术家)。

    在这种情况下,在 songs 集合中存储艺术家的 id 非常好,我们可以放心地假设即使在最坏的情况下 (存储由 100 位艺术家演唱的复杂/多样化的歌曲) 它永远不会强制我们的歌曲集超过 16 MB。

  • 然而,一个艺术家在他的整个职业生涯中可能会唱多达 1000 首或更多的歌曲。 ObjectId 的长度为 12 字节,在这种情况下,集合将增长到仅 12000 字节的大小,远小于 16000000 字节。你仍然有很多空间。因此无需担心达到 16MB 的上限。

方法 - 1

Inter-bucketing works really well for relations expecting high reads.

可以在单个查询中获取某些艺术家的歌曲,反之亦然。如果在这两个集合上散布索引,这将更加顺畅。

但是,如果我们在歌曲中存储艺术家,在艺术家中存储歌曲,那么我们的更新就不再是原子的了,但为此我们仍然可以为艺术家和歌曲 CRUD 实现应用程序级别的两阶段提交,即使在有点麻烦,解决问题。

方法 - 2:

Why not bucket only artist id's inside of songs collection and have multikey index on that field.

演唱歌曲的艺术家列表比艺术家演唱的歌曲列表太短。所以我们只在歌曲收藏中存储艺术家。

这样我们会 -

1.如果我们将歌曲分桶到艺术家收藏中,则可以避免达到艺术家收藏最大尺寸的几乎不可能的可能性。

2. 避免为至少 songs 集合编写 2P 提交。所有关系读取只能通过歌曲集来满足(这里我不包括艺术家的 _id 查找)

3.确保在单个查询中快速访问数据,即使在反向查询艺术家演唱的歌曲的歌曲集时也是如此。

您已经拥有一些需要为其获取歌曲的艺术家的信息(_id)。您只需像这样草拟一个查询 -

 db.songs.find({ artists: 'your-artist-id' });

当您解释这个查询时,当您意识到它利用了您的多键索引时,您会感到很高兴。干得好!

现在选择哪种方法?

我发现第二种方法更适合您的用例,因为它降低了为原子性管理 2P 提交的一些复杂性,并且仍然提供了良好的读取性能。第一种方法肯定是面向读取的,所以如果你确定你会在这两个集合上收到大量的读取,请选择第一个,否则第二个应该可以解决问题。

关于mongodb - 如何处理MongoDB中的多对多关系?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49711032/

相关文章:

mongodb - 多边形外壳无效

mongodb - Windows MongoDB Compass 没有显示集合信息,但 Ubuntu MongoDB Compass 显示了什么?

mongodb - 查询 mongoose 中最后 10 条减去最后 5 条记录

javascript - MongoDB 聚合与带有日期的对象属性嵌套数组

solr - 如何编辑默认创建的 solr 5 架构

database - 为什么 Visual Studio 2010 中的 Schema Compare 在没有差异的情况下显示差异?

java - Spring data mongodb并发获取和更新是线程安全的吗?

javascript - 优化 Node.js 中的组合 MongoDB 查询

javascript - $push value to array with mongoose 只有当键存在时

javascript - Mongoose 类型错误 : Cannot read property 'googleID' of undefined