Это зависит от того, что вы действительно отправляете в качестве входных данных для параметров запроса здесь. Также главное, что вам нужно понять, это то, что это не «ПРИСОЕДИНЯЙТЕСЬ», но на самом деле отдельные запросы выдаются программным слоем mongoose
, поэтому существуют различные различия в обращении.
В базовом случае, когда «значения», поставляемые в качестве параметров, на самом деле являются значениями ссылок, вы фактически просто хотите их непосредственно в основном «запросе», а не в аргументах действия .populate()
(что на самом деле где происходят «дополнительные запросы»).
Кроме того ваши «отношения/ссылки» находятся в Rating
модели, так что, когда ваш запрос выдается вместо:
Rating.find({
"actor": req.actor,
"user": req.user
}).populate("actor user").exec(function(err,ratings) {
// Matched ratings by actor and user supplied
})
Если параметры вместо этого "name"
данные каждого объекта, а затем с той информацией нет в модели Rating
до тех пор, пока не будет заполнен единственный способ mongoose
, чтобы получить «все» объектов Rating
, затем выполните «совокупность» с критериями "match"
и, наконец, отфильтруйте любые результаты, в которых население было null
к несогласованным элементам:
Rating.find().populate([
{ "path": "actor", "match": { "name": req.actor } },
{ "path": "user", "match": { "name": req.user } }
]).exec(function(err,ratings) {
// Now filter out the null results
ratings = ratings.filter(function(rating) {
return (rating.actor != null && rating.user != null)
});
// Then work with filtered data
})
Конечно, это крайне неэффективно, так как это «клиент» операции на стороне, и вы тянете во всей Rating
содержания «первый».Так что вы на самом деле означает сделать в этом случае на самом деле сделать «три» операции запроса самостоятельно, и получать ObjectId
значения из обоих User
и Actor
моделей для того, чтобы применить спичку к Rating
модели вместо:
async.parallel(
{
"user": function(callback) {
User.findOne({ "name": req.user },callback)
},
"actor": function(callback) {
Actor.findOne({ "name": req.actor },callback)
}
},
function(err,data) {
// Use returned _id values in query
Rating.find({
"actor": data.actor._id,
"user": data.user._id
}).populate("actor user").exec(err,ratings) {
// populated Rating results
});
}
)
Затем запросы разрешают «только» ObjectId
значениям, которые вам действительно нужны, а окончательный запрос на Rating
только извлекает те результаты, которые фактически соответствуют условиям, а не все, и выполняют операцию «постфильтр».
В глиссаде, если у вас есть MongoDB 3.2 имеющийся, то вы можете попеременно использовать $lookup
операцию вместо того, чтобы выполнить «СТАЛ» на «сервере» вместо:
Rating.aggregate(
[
{ "$lookup": {
"from": "users",
"localField": "user",
"foreignField": "_id",
"as": "user"
}},
{ "$unwind": "$user" },
{ "$match": { "user.name": req.user } },
{ "$lookup": {
"from": "actors",
"localField": "actor",
"foreignField": "_id",
"as": "actor"
}},
{ "$unwind": "actor" },
{ "$match": { "actor.name": req.actor } }
],
function(err,ratings) {
// populated on the server in one request
}
)
От «клиента» точка зрения, это всего лишь «один» запрос и ответ, в отличие от того, что делает .populate()
. Но на самом деле это не более чем «серверная» версия представления «клиентской» логики, представленная ранее.
Итак, если вы ищете значения "name"
, вместо этого вы должны использовать подход «трех» запросов для оптимальной производительности, поскольку версия агрегации по-прежнему работает с гораздо большим количеством данных, чем нужно.
Конечно, «лучшая» перспектива - просто использовать значения ObjectId
для начала.
Конечно, главное, что информация, подобная "userRating"
, относится к модели Rating
, и именно поэтому вы предоставляете «запрос» во всех случаях для извлечения этих данных. Это не операции «JOIN», как в SQL, поэтому «сервер» не рассматривает объединенные результаты, а затем выбирает поля.
Как немного самообразования включите «отладку», чтобы увидеть, как mongoose
фактически выдает инструкции на сервер. Затем вы увидите, как на самом деле применяется .populate()
:
mongoose.set("debug",true)