如何在mongodb中加入查询?

时间:2010-12-30 14:04:58

标签: join mongodb schema

我有这样的用户文档集:

User {
   id:"001"
   name:"John",
   age:30,
   friends:["userId1","userId2","userId3"....]
}

用户有很多朋友,我在SQL中有以下查询:

select * from user where in (select friends from user where id=?) order by age

我想在MongoDB中有类似的东西。

11 个答案:

答案 0 :(得分:31)

要使用聚合框架的$ lookup功能只使用一个查询来完成所有操作,请尝试以下操作:

db.User.aggregate(
    [
        // First step is to extract the "friends" field to work with the values
        {
            $unwind: "$friends"
        },
        // Lookup all the linked friends from the User collection
        {
            $lookup:
            {
                from: "User",
                localField: "friends",
                foreignField: "_id",
                as: "friendsData"
            }
        },
        // Sort the results by age
        {
            $sort: { 'friendsData.age': 1 }
        },
        // Get the results into a single array
        {
            $unwind: "$friendsData"
        },
        // Group the friends by user id
        {
            $group:
            {
                _id: "$_id",
                friends: { $push: "$friends" },
                friendsData: { $push: "$friendsData" }
            }
        }
    ]
)

假设您的用户集合的内容如下:

{
    "_id" : ObjectId("573b09e6322304d5e7c6256e"),
    "name" : "John",
    "age" : 30,
    "friends" : [
        "userId1",
        "userId2",
        "userId3"
    ]
}
{ "_id" : "userId1", "name" : "Derek", "age" : 34 }
{ "_id" : "userId2", "name" : "Homer", "age" : 44 }
{ "_id" : "userId3", "name" : "Bobby", "age" : 12 }

查询结果将是:

{
    "_id" : ObjectId("573b09e6322304d5e7c6256e"),
    "friends" : [
        "userId3",
        "userId1",
        "userId2"
    ],
    "friendsData" : [
        {
            "_id" : "userId3",
            "name" : "Bobby",
            "age" : 12
        },
        {
            "_id" : "userId1",
            "name" : "Derek",
            "age" : 34
        },
        {
            "_id" : "userId2",
            "name" : "Homer",
            "age" : 44
        }
    ]
}

答案 1 :(得分:30)

编辑:此答案仅适用于v3.2之前的MongoDb版本。

您无法在一个查询中执行所需操作。您必须首先检索朋友用户ID列表,然后将这些ID传递给第二个查询以检索文档并按年龄对它们进行排序。

var user = db.user.findOne({"id" : "001"}, {"friends": 1})
db.user.find( {"id" : {$in : user.friends }}).sort("age" : 1);

答案 2 :(得分:10)

https://docs.mongodb.org/manual/reference/operator/aggregation/lookup/

这是mongodb中的连接查询的文档,这是版本3.2的新功能。

所以这会有所帮助。

答案 3 :(得分:5)

MongoDB没有连接,但在你的情况下你可以这样做:

db.coll.find({friends: userId}).sort({age: -1})

答案 4 :(得分:2)

除了MapReduce之外,似乎没有人谈到使用Pivot的这个选项。 有一篇好文章可以作为你的答案 http://cookbook.mongodb.org/patterns/pivot/ 希望这对您的项目有所帮助

答案 5 :(得分:2)

您可以在Moongoose JS .populate(){ populate : { path : 'field' } }中使用。 示例:

型号:

 mongoose.model('users', new Schema({
        name:String,
        status: true,
        friends: [{type: Schema.Types.ObjectId, ref:'users'}], 
        posts: [{type: Schema.Types.ObjectId, ref:'posts'}], 

    }));
 mongoose.model('posts', new Schema({
            description: String,
            comments: [{type: Schema.Types.ObjectId, ref:'comments'}], 

        }));
 mongoose.model('comments', new Schema({
            comment:String,
            status: true

        }));

如果要查看朋友的帖子,可以使用它。

Users.find().                    //Collection 1
        populate({path:'friends',   //Collection 2
        populate:{path:'posts'   //Collection 3
        }})
    .exec();

如果您想查看朋友的帖子并带上所有评论,也可以使用它,也可以使用它,如果找不到此链接并且查询错误,则可以标识集合。

 Users.find().                                    //Collection 1
        populate({path:'friends',                 //Collection 2
        populate:{path:'posts',                   //Collection 3
        populate:{path:'commets, model:Collection'//Collection 4 and more
        }}})
    .exec();

最后,如果您只想获取某些“集合”的某些字段,则可以使用属性选择“示例”:

Users.find().                                    
        populate({path:'friends', select:'name status friends'                  
        populate:{path:'comments'               
        }})
    .exec();

答案 6 :(得分:1)

在mongoDB中加入一个查询,在一个集合中询问匹配的id,将id放入列表(idlist),并在$ in:idlist

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

答案 7 :(得分:0)

您可以使用playOrm在一个Query中执行您想要的操作(使用S-SQL Scalable SQL)。

答案 8 :(得分:0)

var p = db.sample1.find().limit(2) , 
    h = [];
for (var i = 0; i < p.length(); i++) 
{
  h.push(p[i]['name']);
}
db.sample2.find( { 'doc_name': { $in : h } } ); 

它对我有用。

答案 9 :(得分:0)

您可以使用aggregation pipeline一次性完成。这是它的样子:

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

joinQuery(
    mongoose.models.User,
    {
        find: {},
        populate: ["friends"],
        sort: { age: 1 },
    },
    (err, res) => (err ? console.log("Error:", err) : console.log("Success:", res.results))
);

结果将按年龄排序您的用户,并嵌入所有朋友对象。

它是如何工作的?

幕后mongo-join-query将使用您的Mongoose架构来确定要加入的模型,并创建将执行加入和查询的{{3}}。

答案 10 :(得分:0)

仅填充数组好友。

User.findOne({ _id: "userId"})
.populate('friends')
.exec((err, user) => {
    //do something
});

结果是这样的:

{
    "_id" : "userId",
    "name" : "John",
    "age" : 30,
    "friends" : [
        { "_id" : "userId1", "name" : "Derek", "age" : 34 }
        { "_id" : "userId2", "name" : "Homer", "age" : 44 }
        { "_id" : "userId3", "name" : "Bobby", "age" : 12 }
    ]
}

与此相同:Mongoose - using Populate on an array of ObjectId