如何关联MongoDB中的数据?

xbo*_*nez 6 mongodb nosql

我将字符串与字符串的所有者(每个字符串一个或多个所有者)一起存储在数据库中.

我一直使用MySQL,这是一个传统的关系数据库.在这种情况下,我会将字符串与唯一ID一起存储在一个表中,然后将字符串的唯一ID与第二个表中的所有者(作为多个记录)一起存储.

然后我可以使用SQL Join来获取所有者的字符串.

我现在正在使用MongoDB开发一个项目,我正在做同样的事情.

在使用NoSQL数据库时,这会被认为是错误的方法吗?在使用NoSQL时,我不应该考虑"关系"吗?

我可以想到在MongoDB中实现相同的另一种方法是将它存储起来:

{
    "string": "foobar",
    "owners": [
        "owner1",
        "owner2",
        "owner3"
    ]
}
Run Code Online (Sandbox Code Playgroud)

但是,在这种情况下,我不确定如何搜索"owner1拥有的所有字符串".

Sam*_*aye 6

在使用NoSQL数据库时,这会被认为是错误的方法吗?在使用NoSQL时,我不应该考虑"关系"吗?

关于嵌入的情况有很多问题,而且归结为如此之少.

如果你想嵌入,这里没有提到的事情需要考虑:

  • 文件大小会大幅增加吗?如果是这样,那么文档可能经常在磁盘上移动,这是一件坏事.
  • 相关的行是否有很多连接到我正在处理的集合(即video无法嵌入user).如果是这种情况,则在将冗余数据从相关行复制到子文档时可能会出现问题,尤其是在更新冗余数据时.
  • 我如何才能显示这些结果?

显示结果始终是是否嵌入的关键决定因素.如果需要对大量行(例如1000)进行分页,则需要$slice在常规查询或聚合框架中使用运算符.在1000我承认它可能非常快,但迟早内存操作将变得比正常查询慢(事实上它总是应该).

如果您需要复杂的排序和显示子文档,您可能希望将它们拆分出来,而是具有以下文档结构:

{
    "string": "foobar",
    "owners": [
        ObjectId(),
        ObjectId(),
        ObjectId()
    ]
}
Run Code Online (Sandbox Code Playgroud)

我认为这对于你的数据来说实际上可能是一个更高效的结构,因为owner听起来就像集合中的user一行users.

您可以只引用它们,而不是使用可能更改的用户数据填充子文档_id.这非常简单,因为你可以嵌入这种关系,但同时文档只会增长很少,这有望意味着磁盘不断移动的可能性很小,不仅如此,而是一个较小的工作集,从而创建一个更高性能的整体操作.不仅如此,当然_id所有者很少会改变,所以你最需要的唯一操作就是创建和删除.

回到复杂的排序和分页.有了这些数据,您当然可以owner通过一次往返获得所有ID,然后在另一次往返中,您可以users使用$in允许您需要的复杂显示来查询表中的所有者行和正常查询.

因此,我发现,整体结构非常高效.

当然这个结构取决于你的查询,最好把字符串id放在用户身上,但在这种情况下它不会,因为用户可能会拥有许多字符串,因为我会说它是多个 - >很多嵌入在字符串一侧的关系.

希望这有帮助,我没有绕圈子,


Ser*_*sev 5

为了补充dbaseman的答案:

是的,你的方法似乎没问题.您可以轻松搜索"owner1拥有的所有字符串"

db.collection.find({owners: 'author1'})
Run Code Online (Sandbox Code Playgroud)

这是可能的,因为mongodb以特殊方式处理数组.


McG*_*gle 2

这看起来是正确的方法;但请记住,它始终取决于项目的整体性、目标是什么(性能、灵活性)、您打算运行最多的查询、是否需要运行临时查询以及其他因素。但总的来说,正如您所写,使用嵌套文档是使用联接和外键的正确替代方案。

还要记住最大文档大小(当前为 16MB),如果给定字符串有许多(例如数十万)所有者,这将是一个问题。