database MongoDB 规范化、外键和加入

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5841681/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 08:10:49  来源:igfitidea点击:

MongoDB normalization, foreign key and joining

mongodbforeign-keysnormalizationdatabasenosql

提问by egervari

Before I dive really deep into MongoDB for days, I thought I'd ask a pretty basic question as to whether I should dive into it at all or not. I have basically no experience with nosql.

在我真正深入研究 MongoDB 几天之前,我想我会问一个非常基本的问题,即我是否应该深入研究它。我基本上没有使用 nosql 的经验。

I did read a little about some of the benefits of document databases, and I think for this new application, they will be really great. It is always a hassle to do favourites, comments, etc. for many types of objects (lots of m-to-m relationships) and subclasses - it's kind of a pain to deal with.

我确实阅读了一些关于文档数据库的一些好处,我认为对于这个新应用程序,它们真的很棒。为许多类型的对象(很多 m 到 m 关系)和子类做收藏夹、评论等总是一件麻烦事——处理起来有点痛苦。

I also have a structure that will be a pain to define in SQL because it's extremely nested and translates to a document a lot better than 15 different tables.

我还有一个结构,在 SQL 中定义会很麻烦,因为它是极度嵌套的,并且比 15 个不同的表更好地转换为文档。

But I am confused about a few things.

但我对一些事情感到困惑。

  1. Is it desirable to keep your database normalized still? I really don't want to be updating multiple records. Is that still how people approach the design of the database in MongoDB?

  2. What happens when a user favourites a book and this selection is still stored in a user document, but then the book is deleted? How does the relationship get detached without foreign keys? Am I manually responsible for deleting all of the links myself?

  3. What happens if a user favourited a book that no longer exists and I query it (some kind of join)? Do I have to do any fault-tolerance here?

  1. 保持数据库规范化是否可取?我真的不想更新多个记录。这仍然是人们在 MongoDB 中设计数据库的方式吗?

  2. 当用户收藏一本书并且此选择仍存储在用户文档中,但随后该书被删除时,会发生什么情况?如果没有外键,关系如何分离?我自己手动负责删除所有链接吗?

  3. 如果用户收藏了一本不再存在的书并且我查询了它(某种连接)会发生什么?我必须在这里做任何容错吗?

采纳答案by Tomasz Stanczak

MongoDB doesn't support server side foreign key relationships, normalization is also discouraged. You should embed your child object within parent objects if possible, this will increase performance and make foreign keys totally unnecessary. That said it is not always possible, so there is a special construct called DBRef which allows to reference objects in a different collection. This may be then not so speedy because DB has to make additional queries to read objects but allows for kind of foreign key reference.

MongoDB 不支持服务器端外键关系,也不鼓励规范化。如果可能,您应该将子对象嵌入到父对象中,这将提高性能并使外键完全不必要。也就是说,这并不总是可行的,因此有一个称为 DBRef 的特殊结构,它允许引用不同集合中的对象。这可能不是那么快,因为 DB 必须进行额外的查询来读取对象,但允许某种外键引用。

Still you will have to handle your references manually. Only while looking up your DBRef you will see if it exists, the DB will not go through all the documents to look for the references and remove them if the target of the reference doesn't exist any more. But I think removing all the references after deleting the book would require a single query per collection, no more, so not that difficult really.

您仍然必须手动处理您的参考。只有在查找您的 DBRef 时,您才会看到它是否存在,如果引用的目标不再存在,DB 将不会遍历所有文档来查找引用并删除它们。但我认为在删除这本书后删除所有引用需要对每个集合进行一次查询,没有更多,所以真的没有那么困难。

If your schema is more complex then probably you should choose a relational database and not nosql.

如果您的架构更复杂,那么您可能应该选择关系数据库而不是 nosql。

There is also a book about designing MongoDB databases: Document Design for MongoDB

还有一本关于设计 MongoDB 数据库的书:Document Design for MongoDB

UPDATEThe book above is not available anymore, yet because of popularity of MongoDB there are quite a lot of others. I won't link them all, since such links are likely to change, a simple search on Amazon shows multiple pages so it shouldn't be a problem to find some.

更新上面的书不再可用,但由于 MongoDB 的流行,还有很多其他的书。我不会将它们全部链接起来,因为这些链接可能会改变,在亚马逊上进行简单的搜索会显示多个页面,因此找到一些应该不成问题。

See the MongoDB manual page for 'Manual references' and DBRefsfor further specifics and examples

有关详细信息和示例,请参阅 MongoDB 手册页的“手册参考”和 DBRefs

回答by Francis M. Bacon

Above, @TomaaszStanczak states

上面,@TomaaszStanczak 说

MongoDB doesn't support server side foreign key relationships, normalization is also discouraged. You should embed your child object within parent objects if possible, this will increase performance and make foreign keys totally unnecessary. That said it is not always possible ...

MongoDB 不支持服务器端外键关系,也不鼓励规范化。如果可能,您应该将子对象嵌入到父对象中,这将提高性能并使外键完全不必要。也就是说,这并不总是可能的......

Normalization is not discouraged by Mongo. To be clear, we are talking about two fundamentally different types of relationships two data entities can have. In one, one child entity is ownedexclusively by a parent object. In this type of relationship the Mongo way is to embed.

Mongo 不鼓励规范化。需要明确的是,我们正在讨论两个数据实体可以具有的两种根本不同类型的关系。在一种情况下,一个子实体仅由父对象拥有。在这种类型的关系中,Mongo 的方式是嵌入。

In the other class of relationship two entities exist independently - have independent lifetimes and relationships. Mongo wishes that this type of relationship did not exist, and is frustratingly silent on precisely how to deal with it. Embedding is just not a solution. Normalization is not discouraged, or encouraged. Mongo just gives you two mechanisms to deal with it; Manual refs(analoguous to a key with the foreign key constraint binding two tables), and DBRef(a different, slightly more structured way of doing the same). In this use case SQL databases win.

在另一类关系中,两个实体独立存在 - 具有独立的生命周期和关系。Mongo 希望这种类型的关系不存在,并且对于如何处理它令人沮丧地保持沉默。嵌入不是解决方案。不鼓励或鼓励规范化。Mongo 只是给了你两种处理它的机制;手动引用(类似于具有绑定两个表的外键约束的键)和 DBRef(一种不同的、稍微结构化的方法)。在这个用例中,SQL 数据库获胜。

回答by dougB

The answers of both Tomasz and Francis contain good advice: that "normalization" is not discouraged by Mongo, but that you should first consider optimizing your database document design before creating "document references". DBRefswere mentioned by Tomasz, however as he alluded, are not a "magic bullet" and require additional processing to be useful.

Tomasz 和 Francis 的回答都包含了很好的建议:Mongo 并不反对“规范化”,但是在创建“文档引用”之前,您应该首先考虑优化数据库文档设计。 DBRefs由 Tomasz 提到,但是正如他所暗示的那样,它们不是“灵丹妙药”,需要额外的处理才能有用。

What is now possible, as of MongoDB version 3.2, is to produce results equivalent to an SQL JOINby using the $lookupaggregation pipeline stage operator. In this manner you can have a "normalized" document structure, but still be able to produce consolidated results. In order for this to work you need to create a unique key in the target collection that is hopefully both meaningfuland unique. You can enforce uniqueness by creating a unique index on this field.

从 MongoDB 3.2 版开始,现在可以通过使用$lookup聚合管道阶段运算符生成与 SQL JOIN等效的结果。通过这种方式,您可以拥有“规范化”的文档结构,但仍然能够生成合并的结果。为了使其工作,您需要在目标集合中创建一个唯一的键,希望它既有意义独特。您可以通过在此字段上创建唯一索引来强制唯一性。

$lookupusage is pretty straightforward. Have a look at the documentation here: https://docs.mongodb.com/manual/reference/operator/aggregation/lookup/#lookup-aggregation. Run the aggregate()method on the source collection (i.e. the "left" table). The fromparameter is the target collection (i.e. the "right" table). The localFieldparameter would be the field in the source collection (i.e. the "foreign key"). The foreignFieldparameter would be the matching field in the target collection.

$lookup 的用法非常简单。看看这里的文档:https: //docs.mongodb.com/manual/reference/operator/aggregation/lookup/#lookup-aggregationaggregate()在源集合(即“左”表)上运行该方法。在参数是目标集合(即“右”表)。该localField参数将是源集合中(即“外键”)的领域。该foreignField参数将目标集合中的匹配字段。

As far as orphaned documents, from your question I would presume you are thinking about a traditional RDBMS set of constraints, cascading deletes, etc. Again, as of MongoDB version 3.2, there is native support for document validation. Have a look at this StackOver article: How to apply constraints in MongoDB?Look at the second answer, from JohnnyHK

至于孤立文档,根据您的问题,我假设您正在考虑一组传统的 RDBMS 约束、级联删除等。同样,从 MongoDB 3.2 版开始,有对文档验证的本机支持。看看这篇 StackOver 文章:如何在 MongoDB 中应用约束?看第二个答案,来自 JohnnyHK

Packt Publishers have a bunch of good books on MongoDB. (Full Disclosure: I wrote a couple of them.)

Packt Publishers 有很多关于 MongoDB 的好书。(完全披露:我写了几个。)