I have user document collection like this:
User {
id:\"001\"
name:\"John\",
age:30,
friends:[\"userId1\",\"userId2\",\"userId3\"....]
}
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);
MongoDB doesn't have joins, but in your case you can do:
db.coll.find({friends: userId}).sort({age: -1})
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();
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
}
]
}
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.
You can use playOrm to do what you want in one Query(with S-SQL Scalable SQL).