6

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

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

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

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

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

我可以想到在 MongoDB 中实现相同的另一种方法是像这样存储它:

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

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

4

4 回答 4

6

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

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

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

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

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

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

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

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

您可以参考他们的_id. 这很酷,因为您可以嵌入关系,但同时文档只会增长很少,这希望意味着磁盘不断移动的可能性很小,不仅如此,而且更小的工作集可以创建整体上更高性能的操作。不仅如此,当然_id所有者的身份很少会改变,因此您最有可能需要对这个数据子集进行的唯一操作就是创建和删除。

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

所以我发现这个结构总体上是非常高效的。

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

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

于 2012-12-20T08:34:40.090 回答
5

为了补充 dbaseman 的回答:

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

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

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

于 2012-06-24T12:02:28.010 回答
3

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

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

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

  1. 添加所有者时,$addToSet 以防止重复
  2. 删除所有者时,$pull

两者都记录在这里: http ://docs.mongodb.org/manual/reference/operators/#update-operators-array

于 2012-12-24T11:55:36.450 回答
2

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

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

于 2012-06-24T05:52:39.553 回答