mongodb中如何加入查询?

发布于 2024-10-09 14:22:36 字数 307 浏览 0 评论 0原文

我有这样的用户文档集合:

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 中有类似的东西。

I have user document collection like this:

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

A user has many friends, I have the following query in SQL:

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

I would like to have something similar in MongoDB.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

野心澎湃 2024-10-16 14:22:36

要使用聚合框架的 $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" }
            }
        }
    ]
)

假设您的 User 集合的内容如下:

{
    "_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
        }
    ]
}

To have everything with just one query using the $lookup feature of the aggregation framework, try this :

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" }
            }
        }
    ]
)

Let's say the content of your User collection is the following:

{
    "_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 }

The result of the query will be:

{
    "_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
        }
    ]
}
街角迷惘 2024-10-16 14:22:36

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

您无法仅在一个查询中完成您想要的操作。您必须首先检索好友用户 id 列表,然后将这些 id 传递给第二个查询以检索文档并按年龄对它们进行排序。

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

Edit: this answer only applies to versions of MongoDb prior to v3.2.

You can't do what you want in just one query. You would have to first retrieve the list of friend user ids, then pass those ids to the second query to retrieve the documents and sort them by age.

var user = db.user.findOne({"id" : "001"}, {"friends": 1})
db.user.find( {"id" : {$in : user.friends }}).sort("age" : 1);
¢好甜 2024-10-16 14:22:36

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

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

所以这会很有帮助。

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

This is the doc for join query in mongodb , this is new feature from version 3.2.

So this will be helpful.

十年不长 2024-10-16 14:22:36

您可以在 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();

最后,如果您只想获取某个集合的某些字段,您可以使用属性 select 示例:

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

You can use in Moongoose JS .populate() and { populate : { path : 'field' } }.
Example:

Models:

 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

        }));

If you want to see your friends' posts, you can use this.

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

If you want to see your friends' posts and also bring all the comments, you can use this and too, you can indentify the collection if this not find and the query is wrong.

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

And to finish, if you want get only some fields of some Collection, you can use the propiertie select Example:

Users.find().                                    
        populate({path:'friends', select:'name status friends'                  
        populate:{path:'comments'               
        }})
    .exec();
时间你老了 2024-10-16 14:22:36

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

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

MongoDB doesn't have joins, but in your case you can do:

db.coll.find({friends: userId}).sort({age: -1})
鹤舞 2024-10-16 14:22:36

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} } )

one kind of join a query in mongoDB, is ask at one collection for id that match , put ids in a list (idlist) , and do find using on other (or same) collection with $in : idlist

u = db.friends.find({"friends": ? }).toArray()
idlist= []
u.forEach(function(myDoc) { idlist.push(myDoc.id ); } )
db.friends.find({"id": {$in : idlist} } )
本王不退位尔等都是臣 2024-10-16 14:22:36

仅填充数组好友。

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 - 在数组上使用 Populate ObjectId

Only populate array friends.

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

Result is same like this:

{
    "_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 }
    ]
}

Same this: Mongoose - using Populate on an array of ObjectId

陌上青苔 2024-10-16 14:22:36

您可以使用 playOrm 在一个查询中执行您想要的操作(使用 S-SQL 可扩展 SQL)。

You can use playOrm to do what you want in one Query(with S-SQL Scalable SQL).

千里故人稀 2024-10-16 14:22:36
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 } } ); 

它对我有用。

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 } } ); 

it works for me.

梦归所梦 2024-10-16 14:22:36

您可以使用 mongo-join-query 一次性完成此操作。其外观如下:

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 架构来确定要加入的模型,并创建一个 将执行联接和查询的聚合管道

You can do it in one go using mongo-join-query. Here is how it would look like:

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))
);

The result will have your users ordered by age and all of the friends objects embedded.

How does it work?

Behind the scenes mongo-join-query will use your Mongoose schema to determine which models to join and will create an aggregation pipeline that will perform the join and the query.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文