如何在MongoDB中关联数据?

如何在MongoDB中关联数据?,mongodb,nosql,Mongodb,Nosql,我正在数据库中存储一个字符串以及该字符串的所有者(每个字符串有一个或多个所有者) 我一直使用MySQL,这是一种传统的关系数据库。在这种情况下,我将在一个表中存储字符串和唯一id,然后在第二个表中存储字符串的唯一id和所有者(作为多条记录) 然后,我可以通过所有者使用SQL连接获取字符串 我现在正在使用MongoDB进行一个项目,我正在做与上面相同的事情 在使用NoSQL数据库时,这会被认为是错误的方法吗?在使用NoSQL时,我不应该考虑“关系”吗 在MongoDB中实现同样功能的另一种方法是将

我正在数据库中存储一个字符串以及该字符串的所有者(每个字符串有一个或多个所有者)

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

然后,我可以通过所有者使用SQL连接获取字符串

我现在正在使用MongoDB进行一个项目,我正在做与上面相同的事情

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

在MongoDB中实现同样功能的另一种方法是将其存储如下:

{
    "string": "foobar",
    "owners": [
        "owner1",
        "owner2",
        "owner3"
    ]
}

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

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


还请记住(目前为16MB),如果给定字符串的拥有者很多(比如数十万),那么这将是一个问题。

为了补充dbaseman的答案:

是的,你的方法似乎还可以。您可以轻松搜索“owner1拥有的所有字符串”

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

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

关于嵌入的问题有很多,但归结起来却很少

如果您希望嵌入以下内容,则需要考虑此处未提及的事项:

  • 文档大小是否会大幅增加?如果是这样,那么文档可能会频繁地在磁盘上移动,这是一件坏事
  • 相关行是否有多个连接到我正在处理的集合(即,
    视频
    无法嵌入
    用户
    )。如果是这种情况,则在将冗余数据从相关行复制到子文档中时可能会遇到问题,尤其是在更新该冗余数据时
  • 我需要如何显示这些结果
显示结果始终是决定是否嵌入的关键因素。如果需要对大量行(比如1000行)进行分页,则需要在普通查询或聚合框架中使用
$slice
操作符。在1000点时,我承认它可能相当快,但内存中的操作迟早会比正常的查询慢(事实上它总是应该的)

如果您需要对子文档进行复杂的排序和显示,您可能希望将这些子文档拆分出来,并采用以下文档结构:

{
    "string": "foobar",
    "owners": [
        ObjectId(),
        ObjectId(),
        ObjectId()
    ]
}
我认为这实际上对您的数据来说可能是一个性能更高的结构,因为
所有者
听起来像
用户
集合中的
用户

您可以只引用用户的
\u id
,而不必使用可能更改的数据填充子文档。这是非常可笑的,因为您可以嵌入关系,但同时文档只会增长很小,这意味着持续磁盘移动的可能性很低,不仅如此,还意味着更小的工作集创建了更高性能的总体操作。不仅如此,当然所有者的
\u id
很少会改变,因此您最有可能抛出此数据子集的唯一操作就是创建和删除

回到复杂的排序和分页。有了这些数据,您当然可以通过一次往返获得所有
所有者
ID,然后在另一次往返中,您可以使用
用户
表中的
$in
进行正常查询,从而实现所需的复杂显示

因此,我发现,这种结构总体上是非常有效的

当然,这种结构取决于您的查询,最好将字符串id放在用户身上,但在本例中,情况并非如此,因为用户可能拥有许多字符串,因此我会说,这是一种嵌入在字符串端的多->多关系


希望这会有所帮助,而且我没有兜圈子,

在处理嵌入式数据时,我建议大家熟悉mongo中的原子性行为。 一个好的起点是:

在向“所有者”数组添加/删除用户ObjectId(Sammaye建议)的特定情况下,您需要对字符串文档使用操作,以确保在多次写入该文档时,仍然保持数据完整性

在此操作中,我建议使用以下操作符:

  • 添加所有者时,$addToSet可防止重复
  • 移除所有者时,$pull
  • 此处记录了这两种情况:

    请不要将“NoSQL”用作保护伞。你在使用MongoDB。就这样。“NoSQL”的意思是太多太少:-)谢谢。我不必担心文档的最大大小,因为我不会接近它。我最常见的查询是insert。非常非常少的发现。
    {
        "string": "foobar",
        "owners": [
            ObjectId(),
            ObjectId(),
            ObjectId()
        ]
    }