MongoDB和“加入”[重复]

Posted

技术标签:

【中文标题】MongoDB和“加入”[重复]【英文标题】:MongoDB and "joins" [duplicate] 【发布时间】:2011-05-03 07:18:33 【问题描述】:

我确定 MongoDB 不正式支持“连接”。这是什么意思?

这是否意味着“我们不能将两个集合(表)连接在一起。”?

我认为如果我们将集合 A 中 _id 的值放入集合 B 中的 other_id 中,我们可以简单地连接两个集合吗?

如果我的理解是正确的,MongoDB 可以将两个表连接在一起,例如,当我们运行查询时。这是由写在http://www.mongodb.org/display/DOCS/Schema+Design 中的“参考”完成的。

那么“加入”的真正含义是什么?

我很想知道答案,因为这对于学习 MongoDB 架构设计至关重要。 http://www.mongodb.org/display/DOCS/Schema+Design

【问题讨论】:

最后他们加入了 MongoDB 3.2 mongodb.com/blog/post/thoughts-on-new-feature-lookup 正确,$lookup 是在 MongoDB 3.2 中引入的。详情请见docs.mongodb.org/master/reference/operator/aggregation/lookup/… 加入示例:fourthbottle.com/2016/07/joins-in-mongodb.html 【参考方案1】:

这不是连接,因为只会在需要时评估关系。另一方面,连接(在 SQL 数据库中)将解析关系并将它们返回,就好像它们是单个表一样(您“将两个表连接为一个”)。

您可以在此处阅读有关 DBRef 的更多信息: http://docs.mongodb.org/manual/applications/database-references/

解决引用有两种可能的解决方案。一种是手动完成,正如您几乎描述的那样。只需将一个文档的 _id 保存在另一个文档的 other_id 中,然后编写自己的函数来解决关系。另一种解决方案是使用上面手册页中描述的 DBRefs,这将使 MongoDB 按需解析关系 client-side。您选择哪种解决方案并不重要,因为这两种方法都会在客户端解析关系(请注意,SQL 数据库会在服务器端解析连接)。

【讨论】:

嗯,这是一个正确的答案,但它提出了为什么 MongoDB 不支持这个服务器端的问题?是否只是为了阻止它的使用并鼓励非规范化?非规范化有时在资源上效率太低。在这种情况下,为什么要强制客户端/服务器周转? @groovydotcom 要了解这一点,您必须了解 days 和 nosql 的动机。 Nosql 针对海量读写操作进行了优化。大量的。客户端机器和应用程序服务器比几年前更快。理论是将昂贵的连接操作卸载到应用程序服务器和客户端机器上,以允许数据库服务器尽可能快地简单地处理简单的读写操作。 这意味着什么,更糟糕的情况是,客户需要两个完整的集合,这可能是巨大的,对吧?例如,如果您有一个包含所有用户配置文件的集合,并且您只想存储用户 _id 的内容...? “客户端”和“服务器端”是什么意思? @scaryguy,“服务器端”将在 MongoDB 应用程序中,而“客户端”是您的应用程序代码。您的应用程序作为客户端连接到 MongoDB 服务器。不要将此与机器混淆;两个进程可能在同一台机器上运行。客户端和服务器只是描述了进程间通信中的两种不同角色。【参考方案2】:

您链接到的第一个示例显示了 MongoDB 引用的行为很像延迟加载而不是连接。两个集合上都没有发生查询,而是查询一个,然后通过引用从另一个集合中查找项目。

【讨论】:

【参考方案3】:

数据库不进行连接——或文档之间的自动“链接”。但是你可以在客户端自己做。如果你需要做2,那没关系,但如果你必须做2000,那么客户端/服务器的周转次数会使操作变慢。

在 MongoDB 中,一个常见的模式是嵌入。在关系中,当规范化事情时,会被分成几部分。通常在 mongo 中,这些部分最终会成为单个文档,因此无论如何都不需要连接。但是当需要一个时,一个在客户端执行。

考虑经典的 ORDER、ORDER-LINEITEM 示例。一个订单和 8 个行项在关系中是 9 行;在 MongoDB 中,我们通常会将其建模为单个 BSON 文档,该文档是具有嵌入式订单项数组的订单。因此,在这种情况下,不会出现连接问题。然而,订单会有一个 CUSTOMER,它可能是一个单独的集合——客户端可以从订单文档中读取 cust_id,然后根据需要单独获取它。

我相信的 mongodb.org 网站上有一些架构设计讲座的视频和幻灯片。

【讨论】:

但是以这种情况为例,假设订单有8个订单项,订单项包含sku代码,如何检索具有特定sku的订单。比如说“我想要所有具有 sku 代码的订单:'ABC001'”。 @VijaySali 你搜索它...db.collection.find( "orders.lineitems.SKU" : "ABC001");假设嵌入式订单项具有 S​​KU 字段,您将取回具有该 SKU 的所有订单。这一切都取决于架构【参考方案4】:

在 mongoDB 中加入查询的一种方法是在一个集合中询问匹配的 id,将 id 放入列表 (idlist) 中,并使用 $in 查找其他(或相同)集合:idlist

u = db.friends.find("friends": something ).toArray()
idlist= []
u.forEach(function(myDoc)  idlist.push(myDoc.id );  )
db.family.find("id": $in : idlist  )

【讨论】:

最好是:u = db.friends.find("friends": something ,_id:0,id:1).toArray()db.family.find("id": $in : u )【参考方案5】:

如果你使用猫鼬,你可以使用(假设你使用子文档和人口):

Profile.findById profileId
  .select 'friends'
  .exec (err, profile) ->
    if err or not profile
      handleError err, profile, res
    else
      Status.find  profile:  $in: profile.friends  , (err, statuses) ->
        if err
          handleErr err, statuses, res
        else
          res.json createJSON statuses

它检索属于Profile (profileId) 朋友之一的Statuses。 Friends 是对其他 Profiles 的引用数组。 Profile 架构与 friends 定义:

schema = new mongoose.Schema
  # ...

  friends: [
    type: mongoose.Schema.Types.ObjectId
    ref: 'Profile'
    unique: true
    index: true
  ]

【讨论】:

此问题未在“CoffeeScript”中标记。如果你想举个例子,恕我直言,这个例子应该是 javascript 的。 CoffeScript 不是 JavaScript。 未被标记为 JavaScript。 JavaScript 是 MongoDB 的官方 shell 查询语言...【参考方案6】:

mongoDB 不是关系型的事实导致some people to consider it useless。 我认为在设计数据库之前你应该知道你在做什么。如果您选择使用 MongoDB 等 noSQL DB,则最好实现一个模式。这将使您的集合或多或少类似于 SQL 数据库中的表。此外,避免非规范化(嵌入),除非出于效率原因需要。

如果您想设计自己的 noSQL 数据库,我建议您查看Firebase 文档。如果您了解他们如何为他们的服务组织数据,您可以轻松地为您的服务设计一个类似的模式。

正如其他人指出的那样,您必须在客户端执行连接,除了 Meteor(一个 Javascript 框架)之外,您可以使用此 package 在服务器端执行连接(我不知道其他使您能够这样做的框架)。但是,我建议您在决定选择此选项之前阅读此article。

编辑 28.04.17: 最近 Firebase 发布了这篇关于设计 noSql 数据库的excellent series。他们还在one of the episodes 中强调了避免连接的原因以及如何通过非规范化数据库来解决此类情况。

【讨论】:

【参考方案7】:

我遇到了很多搜索相同的帖子 - “Mongodb Joins”和替代品或等价物。所以我的回答会帮助很多和我一样的人。这就是我要寻找的答案。

我正在使用带有 Express 框架的 Mongoose。有一个名为 Population 的功能代替了连接。

正如猫鼬docs 中所述。

MongoDB 中没有连接,但有时我们仍希望引用其他集合中的文档。这就是人口的来源。

*** answer 展示了一个简单的使用示例。

【讨论】:

以上是关于MongoDB和“加入”[重复]的主要内容,如果未能解决你的问题,请参考以下文章

MongoDb - “加入”集合[重复]

mongodb带密码的副本集加入分片后怎么访问

学习MongoDB 二:MongoDB加入删除改动

将MongoDB服务加入随机启动

通过 Azure Data Lake 和 Power BI 进行数据分析(加入 mongoDB 和 SQL 数据)

使用聚合 $lookup 加入 mongodb