如何关联MongoDB中的数据?

时间:2012-06-24 05:23:46

标签: mongodb nosql

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

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

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

我现在正在使用MongoDB开发一个项目,我的工作与上面相同。

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

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

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

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

4 个答案:

答案 0 :(得分:6)

  

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

关于嵌入的情况有很多问题,而且归结为很少。

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

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

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

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

{
    "string": "foobar",
    "owners": [
        ObjectId(),
        ObjectId(),
        ObjectId()
    ]
}

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

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

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

总而言之,我发现这种结构非常有效。

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

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

答案 1 :(得分:5)

补充dbaseman的答案:

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

db.collection.find({owners: 'author1'})

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

答案 2 :(得分:3)

在处理嵌入数据时,我建议您熟悉mongo中的Atomicity行为。 一个很好的起点将在这里: http://docs.mongodb.org/manual/core/data-modeling/#atomicity

在您的特定情况下,将用户ObjectId(由Sammaye推荐)添加/删除到“所有者”数组时,您将需要对字符串doc使用a findAndModify()操作以确保写入该文档时,仍然保持数据完整性。

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

  1. 添加所有者时,$ addToSet以防止重复
  2. 删除所有者时,$ pull
  3. 这两个都记录在这里: http://docs.mongodb.org/manual/reference/operators/#update-operators-array

答案 3 :(得分:2)

这看起来像是正确的方法;但请记住,它总是取决于项目的总体情况,目标是什么(性能,灵活性),您打算运行最多的查询,是否需要运行即席查询以及其他因素。通常,使用嵌套文档,如您所写,是使用连接和外键的正确替代方法。

还要记住maximum document size(目前是16MB),如果有很多(如数十万)给定字符串的所有者,这将是一个问题。