我确信MongoDB没有正式支持“加入”。这是什么意思?
这是否意味着“我们无法将两个集合(表格)连接在一起。”?
我认为如果我们将集合A中_id
的值放入集合B中的other_id
,我们可以简单地连接两个集合吗?
如果我的理解是正确的,MongoDB可以将两个表连接在一起,比如说,当我们运行查询时。这是通过http://www.mongodb.org/display/DOCS/Schema+Design中的“参考”来完成的。
然后“加入”真正意味着什么?
我很想知道答案,因为这对学习MongoDB架构设计至关重要。 http://www.mongodb.org/display/DOCS/Schema+Design
答案 0 :(得分:97)
这不是连接,因为只有在需要时才会评估关系。另一方面,连接(在SQL数据库中)将解析关系并将它们作为单个表返回(您将“将两个表连接成一个”)。
您可以在此处阅读有关DBRef的更多信息: http://docs.mongodb.org/manual/applications/database-references/
解决参考文献有两种可能的解决方案。一个是手动完成,正如你几乎所描述的那样。只需将文档的_id保存在另一个文档的other_id中,然后编写自己的函数来解决关系。另一种解决方案是使用上面手册页中描述的DBRef,这将使MongoDB按需解析客户端的关系。您选择哪种解决方案并不重要,因为这两种方法都将解决客户端关系(请注意,SQL数据库会解析服务器端的连接)。
答案 1 :(得分:49)
从Mongo 3.2开始,这个问题的答案已不再正确。添加到聚合管道的新$ lookup运算符与左外连接基本相同:
https://docs.mongodb.org/master/reference/operator/aggregation/lookup/#pipe._S_lookup
来自文档:
{
$lookup:
{
from: <collection to join>,
localField: <field from the input documents>,
foreignField: <field from the documents of the "from" collection>,
as: <output array field>
}
}
答案 2 :(得分:30)
数据库不进行连接 - 或者在文档之间自动“链接”。但是你可以自己做客户端。如果你需要做2,那没关系,但如果你不得不做2000,那么客户/服务器周转的数量会使操作变慢。
在MongoDB中,一种常见的模式是嵌入。正常化时,事物会被分解成几部分。通常在mongo中,这些部分最终成为单个文档,因此无论如何都不需要加入。但是当需要一个时,就会在客户端做到这一点。
考虑经典的ORDER,ORDER-LINEITEM示例。一个订单和8个订单项相关的是9行;在MongoDB中,我们通常只将其建模为单个BSON文档,该文档是包含嵌入行项目数组的订单。因此,在这种情况下,不会出现连接问题。但是,订单将有一个CUSTOMER,它可能是一个单独的集合 - 客户端可以从订单文档中读取cust_id,然后根据需要单独获取它。
我相信mongodb.org网站上有一些关于架构设计会谈的视频和幻灯片。
答案 3 :(得分:12)
在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} } )
答案 4 :(得分:6)
您链接的第一个示例显示了MongoDB引用的行为方式与延迟加载非常类似,不像连接。这两个集合上都没有查询,而是查询一个,然后通过引用从另一个集合中查找项目。
答案 5 :(得分:5)
mongoDB不是关系的事实导致了some people to consider it useless。 我认为在设计数据库之前你应该知道自己在做什么。如果您选择使用noSQL DB(如MongoDB),则最好实现架构。这将使您的集合 - 或多或少 - 类似于SQL数据库中的表。此外,避免非规范化(嵌入),除非出于效率原因需要。
如果您想设计自己的noSQL数据库,我建议您查看Firebase文档。如果您了解他们如何为他们的服务组织数据,您可以轻松地为您设计类似的模式。
正如其他人指出的那样,除了使用Meteor(一个Javascript框架)之外,你必须在客户端进行连接,你可以使用这个package来加入服务器端(我不喜欢#39;了解其他框架,使您能够这样做)。但是,我建议您在决定选择之前阅读此article。
编辑28.04.17: 最近Firebase在设计noSql数据库时发布了这个excellent series。他们还在one of the episodes中强调了避免连接的原因以及如何通过对数据库进行非规范化来解决这些问题。
答案 6 :(得分:2)
考虑使用猫鼬?它使您能够对mongo数据进行连接。
答案 7 :(得分:1)
如果你使用mongoose,你可以使用(假设你正在使用子文档和人口):
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
它会检索属于Statuses
(Profile
)朋友之一的profileId
。 Friends是对其他Profiles
的引用数组。定义了Profile
的{{1}}架构:
friends
答案 8 :(得分:1)
你可以使用MongoDB插件,它很棒,并且允许加入,合并和创建查询构建器 试试吧 : https://github.com/petersirka/mongodb-addons
答案 9 :(得分:0)
作为MongoDB的用户,我不得不经常从相关集合中获取数据。当人们将关系数据库的数据存储到NoSQL数据库中时,“加入”确实是必要的。这是一个库,我和我的朋友一起在Python中执行Mongo Joins -
https://pypi.python.org/pypi/mongojoin/1.0.0
代码不是太复杂,值得一试!
答案 10 :(得分:0)
我遇到了许多搜索相同内容的帖子 - &#34; Mongodb Joins&#34;和替代品或等同物。所以我的答案会帮助许多像我一样的人。这就是我要找的答案。
我正在使用Mongoose和Express框架。有一个名为Population
的功能代替了连接。
如Mongoose docs中所述。
MongoDB中没有连接,但有时我们仍然希望引用其他集合中的文档。这就是人口涌入的地方。
这个StackOverflow answer显示了一个如何使用它的简单示例。