Abh*_*ngh 8 schema entity-relationship mongoose mongodb
我在MongoDB中有很多关系实现的特定问题.
我有歌曲和艺术家的集合(百万文档).歌曲可以由多位艺术家演唱,艺术家可以唱很多歌.所以我在两个集合中都遵循了文档引用的方法.像这样...
1. 歌曲收藏: -
{
_id:ObjectId("dge547567hheheasfw3454dfg"),
title:"xyz",
artists:[ObjectId("xfvdg464654"), ...] //many artists // artists ids
}
Run Code Online (Sandbox Code Playgroud)
2. 艺术家收藏: -
{
_id:ObjectId("dge547567hheheasfw3454dfg"),
title:"xyz",
songs:[ObjectId("xfvdg464654"), ...] //many songs // songs Ids
}
Run Code Online (Sandbox Code Playgroud)
但这里的问题是在对一个集合进行CRUD操作时,我必须对其他集合进行CRUD操作.就像删除艺术家一样,我必须在艺术家的歌曲的所有文档中删除艺术家阵列中的艺术家.这可能会导致原子性问题. 我怎样才能确保这里的原子性?
其次,当数据库将增长并且艺术家演唱的歌曲将增加时,因此结果文档增长的收集和文档大小可以达到16MB或更大(MAX DOC SIZE).
那么在这种情况下可以做些什么呢?
让我们首先详细说明您的案例的多对多关系,并尝试了解可以做什么和不可做什么 -
一首歌可以由多达10位或大约20位艺术家演唱(假设它不像复杂/多样化那样需要100位艺术家).
在这种情况下,songs收藏艺术家在收藏中的内容非常好,我们可以安全地假设,即使在最糟糕的情况下(存储由100位艺术家演唱的复杂/多样化的歌曲),它也绝不会强制我们的歌曲收集超过16 MB.
然而,一位艺术家可能会很好地演唱多达1000首歌曲,或者更多的是在他的职业生涯中.一个12字节长的ObjectId,在这种情况下,将一个集合增长到仅12000字节的大小,这比16000000字节小.你仍然留有很大的空间.因此无需担心达到16MB的上限.
方法 - 1
Inter-bucketing对于期望高读取的关系非常有效.
一些艺术家的歌曲可以在单个查询中获取,反之亦然.在这两个集合上撒上索引,这将更加平滑.
但是如果我们围绕艺术家里面的歌曲和歌曲中的艺术家,那么我们的更新不再是Atomic,但为此我们仍然可以为艺术家和歌曲CRUD实现应用程序级别两阶段提交,即使在有点麻烦之后,解决了这个问题.
方法 - 2:
为什么不在歌曲集合中仅存储艺术家ID,并在该字段上具有多键索引.
唱歌的艺术家名单比艺术家演唱的歌曲名单太短.因此,我们只在歌曲集合中挖掘艺术家.
这样我们会 -
1.如果我们在艺术家收藏中放置了一些分段的歌曲,请避免几乎不可能达到艺术家收藏的最大尺寸.
2.避免为至少songs集合编写2P提交.所有关系读取只能通过歌曲收集来满足(这里我不包括艺术家的_id查找)
3.即使在对艺术家演唱的歌曲的歌曲集合进行反向查询时,也只需一次查询即可确保快速访问数据.
你已经有了一些你需要获取歌曲的艺术家信息(_id).你只需起草一个这样的查询 -
db.songs.find({ artists: 'your-artist-id' });
Run Code Online (Sandbox Code Playgroud)
当你解释这个查询时,当你意识到它利用你的多键索引时,你会发现快乐.干得好!
现在采用哪种方法?
我发现第二种方法对于您的用例更为微妙,因为它降低了管理2P提交原子性的一些复杂性,并且仍然提供了良好的读取性能.第一种方法绝对是面向读取的,所以如果你确定你将收到很多很多关于这两个集合的读取,那就去找第一个,否则第二个就应该做.
| 归档时间: |
|
| 查看次数: |
191 次 |
| 最近记录: |