我如何在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"  }

是否有一种方法可以一次性提取具有特定字段的所有评论(例如. ...find({pid:444}))和与每个评论相关的用户信息?

目前,我首先获取符合条件的注释,然后找出结果集中的所有uid,获取用户对象,并将它们与注释的结果合并。看来我做错了。


当前回答

不,看起来你并没有做错。MongoDB连接是“客户端”。就像你说的

目前,我首先获取符合条件的注释,然后找出结果集中的所有uid,获取用户对象,并将它们与注释的结果合并。看来我做错了。

1) Select from the collection you're interested in.
2) From that collection pull out ID's you need
3) Select from other collections
4) Decorate your original results.

它不是一个“真正的”连接,但它实际上比SQL连接有用得多,因为您不必处理“多”面连接的重复行,而是修饰最初选择的集合。

这一页上有很多废话和FUD。结果5年后,MongoDB仍然存在。

其他回答

你可以在Mongo中使用3.2版本提供的查找来连接两个集合。在您的情况下,查询将是

db.comments.aggregate({
    $lookup:{
        from:"users",
        localField:"uid",
        foreignField:"uid",
        as:"users_comments"
    }
})

或者你也可以加入关于用户,然后会有一个小的变化如下所示。

db.users.aggregate({
    $lookup:{
        from:"comments",
        localField:"uid",
        foreignField:"uid",
        as:"users_comments"
    }
})

它的工作原理与SQL中的左连接和右连接一样。

下面是一个“join”* Actors和Movies集合的例子:

https://github.com/mongodb/cookbook/blob/master/content/patterns/pivot.txt

它使用了.mapReduce()方法

join -在面向文档的数据库中加入的替代方案

您可以使用聚合管道来实现它,但是自己编写它很麻烦。

您可以使用mongo-join-query从您的查询自动创建聚合管道。

这是你的查询的样子:

const mongoose = require("mongoose");
const joinQuery = require("mongo-join-query");

joinQuery(
    mongoose.models.Comment,
    {
        find: { pid:444 },
        populate: ["uid"]
    },
    (err, res) => (err ? console.log("Error:", err) : console.log("Success:", res.results))
);

您的结果将在uid字段中有user对象,您可以链接任意多的层次。您可以填充对用户的引用,从而引用一个Team,再引用其他东西,等等。

免责声明:我编写了mongo-join-query来解决这个问题。

你必须按照你描述的方法去做。MongoDB是非关系数据库,不支持连接。

你可以使用Postgres中的mongo_fdw在MongoDB上运行包括join在内的SQL查询。