Как присоединиться к запросу в mongodb?
У меня есть коллекция документов пользователя, как это:
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.
Ответы
Ответ 1
Изменение: этот ответ относится только к версиям MongoDb до v3.2.
Вы не можете делать то, что вы хотите, всего за один запрос. Сначала вам нужно получить список идентификаторов друзей, а затем передать эти идентификаторы во второй запрос, чтобы получить документы и отсортировать их по возрасту.
var user = db.user.findOne({"id" : "001"}, {"friends": 1})
db.user.find( {"id" : {$in : user.friends }}).sort("age" : 1);
Ответ 2
Чтобы иметь всего лишь один запрос, используя функцию $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
}
]
}
Ответ 3
https://docs.mongodb.org/manual/reference/operator/aggregation/lookup/
Это документ для запроса соединения в mongodb, это новая функция из версии 3.2.
Итак, это будет полезно.
Ответ 4
MongoDB не имеет объединений, но в вашем случае вы можете сделать:
db.coll.find({friends: userId}).sort({age: -1})
Ответ 5
Похоже, никто не говорил об этом варианте использования Pivot в добавлении к MapReduce.
Есть хорошая статья, которая может быть вашим ответом здесь
http://cookbook.mongodb.org/patterns/pivot/
Надеюсь, это поможет вам в ваших проектах.
Ответ 6
один вид соединения запроса в mongoDB, запрашивается в одной коллекции для идентификатора, который соответствует, помещает идентификаторы в список (список 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
Вы можете использовать playOrm, чтобы делать то, что вы хотите, в одном запросе (с S-SQL масштабируемым SQL).
Ответ 8
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
Вы можете сделать это за один раз, используя 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, чтобы определить, к каким моделям присоединиться, и создаст конвейер агрегации , который будет выполнять join и запрос.
Ответ 10
Только заполнить массив друзей.
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