当前位置: 首页 > 知识库问答 >
问题:

如何在mongoDB中处理多对多关系?

常温文
2023-03-14

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

我收集了歌曲和艺术家的作品(数百万份文档)。在这里,这首歌可以被许多艺术家演唱,一个艺术家可以唱许多首歌。所以我在两个集合中都遵循了文档引用的方法。像这样...

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 
}

但这里的问题是,在删除艺术家的同时,我必须从歌曲所有文档中的艺术家html" target="_blank">数组中删除一个艺术家,如果该文档中有艺术家,反之亦然。这会导致原子性问题。我如何确保这里的原子性?

其次,当数据库增长并且艺术家演唱的歌曲将增加时,因此由此产生的集合和文档大小的文档增长可以达到16MB或更大(MAX DOC SIZE)。

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

共有2个答案

彭星津
2023-03-14

我在mongoDB中实现了多对多关系,采用了类似于我们在sql中所做的第三个集合。

歌曲合集

{
  _id:ObjectId("dge547567hheheasfw3454df12"),
   title:"xyz",
   length : 123
}

艺术家收藏

{
   _id:ObjectId("dge547567hheheasfw3454d32"),
   name:"abc",
}

歌曲艺术家收藏

{
   _id:ObjectId("dge547567hheheasdfsdfsdfgdfga42"),
   artist: ObjectId("dge547567hheheasfw3454dfg32"),
   song: ObjectId("dge547567hheheasfw3454df12"),
}
    < li >现在,当您执行crud操作时,如果您想从歌曲中删除艺术家,您可以在SongArtist Collection中的单个查询中完成。 < li >它永远不会有超出文件尺寸的问题 < li >如果您想删除特定歌曲中的特定艺术家,您必须查询一次 < li >这将增加集合中的记录数量,但mongodb可以轻松处理这一点。 < li >您可以在单个查询中找到与一位艺术家相关的所有歌曲,反之亦然。
潘哲
2023-03-14

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

> < li>

一首歌可以由多达10位或20位艺术家演唱(假设不需要100位艺术家的复杂/多样性)。

在这种情况下,将艺术家的ID放在歌曲收藏中是完全可以的,我们可以放心地假设,即使在最坏的情况下(存储由100位艺术家演唱的复杂/多样化的歌曲),它也永远不会迫使我们的歌曲收藏超过16 MB。

然而,一个艺术家在他的职业生涯中很可能会演唱多达1000首或更多的歌曲。一个12字节长的ObjectId将使集合的大小仅为12000字节,远低于16000000字节。你仍然有很多空间。所以不用担心达到16MB的上限。

方法 - 1

对于期待高阅读量的关系来说,互扣非常有效。

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

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

方法2:

为什么不在歌曲集合中只存储艺术家id,并在该字段中设置多键索引。

唱过一首歌的艺术家列表比一个艺术家唱过的歌曲列表短得多。所以我们只收集歌曲中的艺术家。

这样我们会-

1.如果我们在艺术家收藏中有带扣的歌曲,避免几乎不可能达到艺术家收藏的最大规模。

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

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

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

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

当你解释这个查询时,当你意识到它利用了你的多键索引时,你会发现快乐。那里的工作很棒!

现在该采取哪种方法?

我发现第二种方法对您的用例来说更微妙一些,因为它降低了管理原子性2P提交的复杂性,并且仍然提供了良好的读取性能。第一种方法肯定是面向读取的,所以如果你确定你将在两个集合上收到很多很多的读取,那么就用第一种方法,否则第二种方法应该可以。

 类似资料:
  • 问题内容: 在关系数据库中,我有一个用户表,一个类别表和一个用户类别表,它们之间存在多对多关系。在Redis中具有这种结构的更好形式是什么? 问题答案: 使用Redis,关系通常由集合表示。一组可用于表示单向关系,因此每个对象需要一组以表示多对多关系。 尝试将关系数据库模型与Redis数据结构进行比较是毫无用处的。使用Redis,所有内容均以非规范化方式存储。 例: 一旦有了此数据结构,就可以使用

  • 问题内容: 我相信标题是不言而喻的。如何在PostgreSQL中创建表结构以建立多对多关系。 我的例子: 问题答案: SQL DDL(数据定义语言)语句如下所示: 我强烈建议您这样做,因为产品名称几乎不是唯一的(不是很好的“自然键”)。此外,强制使用唯一性并在外键中引用该列通常比使用存储为或的字符串便宜(4字节(甚至8字节))。 不要使用基本数据类型的名称作为 标识符 。尽管这是可能的,但这是不好

  • 问题内容: 我正在制作一个具有多对多关系的SQLite数据库,并使用以下代码将其分解为两个一对多的关系 错误: 有谁知道我该如何解决这个错误? 问题答案: 查看文档; 它向您表明,如果您在字段定义本身上指定了外键,则不应使用关键字本身。此外,正如 CL 指出的那样,您使用了太多逗号 。 ,即使单独指定约束,外键名称也不应放在括号中。 该语句可以满足您的要求: 还要注意,如果MODULEID是表MO

  • 不幸的是,Quarkus关于用Panache使用MongoDB的指南没有提到什么被认为是处理实体的一对多关系的最佳实践。注意:我想为依赖的子文档建模,但作为一个独立的实体。MongoDB站点演示了这种模式:用文档引用建模一对多关系,这样您就必须在存储库中查找链接到父ID的所有实体。 Quarkus(Panache)目前是否提供了任何使查找更方便的方法? PS:似乎从2020年5月开始有一个开放的增

  • 作为这个问题的一个例子,让我使用电视节目、电影和演员。每个电视节目和电影都有多个演员,每个演员都在一个或多个电视节目和/或电影中。如果我在他们之间建立一个多态的多对多关系,我似乎可以分别查询一个演员的所有电视节目和所有电影,但尽管我可以用谷歌搜索,我还没有找到一种方法来查询一个演员的所有电视节目和/或电影在一个集合中的联合。这难道不是多对多多态关系的有用之处吗? 如果事实证明这确实是可能的,我可能

  • 我正在做一个小型的laravel项目来实现雄辩的关系,我主要有多个模型(项目、任务、用户、文件等) 一个项目可以分配多个用户,附加多个文件,也可以有多个任务。一个任务可以分配多个用户,也可以分配多个文件,以及多个其他东西。我已经谷歌和实施了hasManyPass,和归属许多关系,但我对关系感到困惑很多。有什么帮助吗? Project.php Task.php User.php 我得到的错误是,当我