我有这样的用户文档集:
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中有类似的东西。
答案 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 }
]
}