如何在MongoDB中执行SQL Join等效操作?
例如,假设你有两个集合(用户和评论),我想用pid = 444以及每个集合的用户信息来提取所有评论 .
comments
{ uid:12345, pid:444, comment="blah" }
{ uid:12345, pid:888, comment="asdf" }
{ uid:99999, pid:444, comment="qwer" }
users
{ uid:12345, name:"john" }
{ uid:99999, name:"mia" }
有没有办法用一个字段拉出所有评论(例如......查找({pid:444}))和一次性与每个评论相关的用户信息?
目前,我首先得到符合我标准的评论,然后找出该结果集中的所有uid,获取用户对象,并将它们与评论的结果合并 . 好像我做错了 .
19 回答
我们可以使用mongodb客户端控制台将只有一行的简单函数合并/加入一个集合中的所有数据,现在我们可以执行所需的查询 . 下面是一个完整的例子
.-作者:
.-分类:
.-书籍
.-图书借阅
. - 魔法:
.-获取新的收集数据:
.-响应:)
我希望这条线可以帮到你 .
playORM可以使用S-SQL(可伸缩SQL)为您完成,它只是添加分区,以便您可以在分区中进行连接 .
$ lookup(聚合)
对同一数据库中的未整数集合执行左外连接,以过滤“已连接”集合中的文档以进行处理 . 对于每个输入文档,$ lookup阶段添加一个新的数组字段,其元素是来自“已连接”集合的匹配文档 . $ lookup阶段将这些重新整形的文档传递给下一个阶段 . $ lookup阶段具有以下语法:
平等比赛
要在输入文档中的字段与“已连接”集合的文档中的字段之间执行相等匹配,$ lookup阶段具有以下语法:
该操作将对应于以下伪SQL语句:
Mongo URL
不,似乎你做错了 . MongoDB加入是“客户端” . 非常像你说的:
它不是一个“真正的”连接,但实际上它比SQL连接更有用,因为你不必处理“多”面连接的重复行,而是装饰最初选择的集合 .
这个页面上有很多废话和FUD . 5年后,MongoDB仍然是一个问题 .
你必须按照你描述的方式去做 . MongoDB是一个非关系型数据库,不支持连接 .
官方mongodb网站上的这个页面正好解决了这个问题:
http://docs.mongodb.org/ecosystem/tutorial/model-data-for-ruby-on-rails/
通过 $lookup , $project 和 $match 的正确组合,您可以在多个参数上连接多个表 . 这是因为它们可以链接多次 .
假设我们想做以下(reference)
Step 1: Link all tables
您可以根据需要查找任意数量的表 .
$lookup - 查询中每个表一个
$unwind - 因为数据是非正规化的,否则包裹在数组中
Python代码..
Step 2: Define all conditionals
$project :在此定义所有条件语句,以及您要选择的所有变量 .
Python代码..
Step 3: Join all the conditionals
$match - 使用OR或AND等连接所有条件 . 可以有多个这些条件 .
$project :取消定义所有条件
Python代码..
几乎任何表,条件和连接的组合都可以这种方式完成 .
在 3.2.6 之前,Mongodb不像mysql那样支持连接查询 . 以下解决方案适合您 .
从Mongo 3.2开始,这个问题的答案大多不再正确 . 添加到聚合管道的新$ lookup运算符与左外连接基本相同:
https://docs.mongodb.org/master/reference/operator/aggregation/lookup/#pipe._S_lookup
来自文档:
当然Mongo不是一个关系数据库,开发人员正在小心推荐$ lookup的特定用例,但至少是3.2现在可以使用MongoDB进行连接 .
有一个规范,许多驱动程序支持称为DBRef .
摘自MongoDB文档:数据模型>数据模型参考> Database References
您可以使用3.2版本中提供的查找在Mongo中加入两个集合 . 在您的情况下,查询将是
或者您也可以加入用户,然后会有一点变化,如下所示 .
它将与SQL中的左右连接一样工作 .
以下是"join" * Actors 和 Movies 集合的示例:
https://github.com/mongodb/cookbook/blob/master/content/patterns/pivot.txt
它使用
.mapReduce()
方法*** join** - 加入面向文档的数据库的替代方案
我认为,如果您需要规范化数据表 - 您需要尝试其他一些数据库解决方案 .
但是我已经在_355251上找到了MOngo的溶剂 . 顺便说一下,在插入代码中 - 它有电影的名字, but noi movie's ID .
问题
你有一系列演员,他们已经完成了一系列电影 .
您想要生成一组电影,每个电影都有一系列演员 .
一些样本数据
解决方案
我们需要遍历Actor文档中的每个影片并单独发出每个影片 .
这里的问题是在减少阶段 . 我们无法从reduce阶段发出数组,因此我们必须在返回的“value”文档中构建一个Actors数组 .
代码
请注意actor_list实际上是一个包含数组的javascript对象 . 另请注意, Map 会发出相同的结构 .
运行以下命令执行map / reduce,将其输出到“pivot”集合并打印结果:
printjson(db.actors.mapReduce(map,reduce,“pivot”)); db.pivot.find()的forEach(printjson) .
以下是样本输出,请注意“漂亮女人”和“失控新娘”都有“Richard Gere”和“Julia Roberts” .
这取决于你想要做什么 .
您目前将其设置为规范化数据库,这很好,并且您采用的方式也是合适的 .
但是,还有其他方法可以做到这一点 .
您可以拥有一个帖子集合,其中包含对每个帖子的嵌入评论,并引用您可以迭代查询的用户 . 您可以将用户的名称与注释一起存储,您可以将它们全部存储在一个文档中 .
NoSQL的用途是它设计用于灵活的模式和非常快速的读写 . 在典型的大数据服务器场中,数据库是最大的瓶颈,数据库引擎比应用程序和前端服务器更少......它们更昂贵但功能更强大,硬盘空间也比较便宜 . 规范化来自于试图节省空间的概念,但它带来了使数据库执行复杂连接和验证关系完整性,执行级联操作的成本 . 如果他们正确地设计了数据库,所有这些都会让开发人员感到头疼 .
对于NoSQL,如果您认为冗余和存储空间不是问题,因为它们的成本(执行更新所需的处理器时间和存储额外数据的硬盘驱动器成本),非规范化不是问题(对于嵌入式阵列而言)数十万个项目可能是性能问题,但大多数时候这不是问题) . 此外,您将为每个数据库集群提供多个应用程序和前端服务器 . 让他们完成连接的繁重工作,让数据库服务器坚持读写 .
TL; DR:对于一些很好的例子你是什么're doing is fine, and there are other ways of doing it. Check out the mongodb documentation'的数据模型模式 . http://docs.mongodb.org/manual/data-modeling/
您可以使用Postgres的mongo_fdw运行SQL查询,包括使用MongoDB加入 .
我们可以使用mongoDB子查询合并两个集合 . 这是一个例子,评论 -
Userss--
用于JOIN的MongoDB子查询 -
从新生成的Collection中获取结果 -
结果 -
希望这会有所帮助 .
正如其他人已经指出你试图从无关系数据库创建一个关系数据库,你真的不想这样做,但是如果你有一个案例你必须这样做,这是一个你可以使用的解决方案 . 我们首先在集合A上找到一个foreach查找(或在你的用例中用户),然后我们将每个项目作为一个对象,然后我们使用对象属性(在你的情况下为uid)在我们的第二个集合中查找(在你的案例评论中)如果我们可以找到它然后我们有一个匹配,我们可以打印或做一些事情 . 希望这能帮助你,祝你好运:)
MongoDB不允许连接,但您可以使用插件来处理那 . 检查mongo-join插件 . 这是最好的,我已经使用过它 . 您可以像这样使用npm直接安装它
npm install mongo-join
. 你可以看看full documentation with examples .()当我们需要加入(N)集合时真正有用的工具
( - )我们可以在查询的顶层应用条件
Example
您可以使用聚合管道来完成它,但是自己编写它会很痛苦 .
您可以使用mongo-join-query从查询中自动创建聚合管道 .
这是您的查询的样子:
您的结果将在
uid
字段中包含用户对象,您可以根据需要链接多个级别 . 您可以填充对用户的引用,该引用引用了一个Team,它引用了其他内容等 .Disclaimer :我写了
mongo-join-query
来解决这个确切的问题 .