这取决于您在此处实际发送的作为查询参数输入的内容。此外,您需要了解的主要内容是,这不是“JOIN”,而是由mongoose 软件层发出的单独查询,因此在处理上存在明显差异。
在作为参数提供的“值”实际上是引用的ObjectId 值的基本情况下,您实际上只希望这些直接在主“查询”中而不是.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 可以做到这一点的唯一方法是检索“所有”@ 987654330@ 对象,然后使用"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 内容。因此,在这种情况下,您真正要做的是自己实际执行“三个”查询操作,并从User 和Actor 模型中获取ObjectId 值,以便将匹配应用于@987654338改为@模型:
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 操作来代替在“服务器”上执行“JOINS”:
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 模型,因此您在所有情况下都提供“查询”以检索该数据。这些不是 SQL 中的“JOIN”操作,因此“服务器”不会查看组合结果然后选择字段。
作为一些自我教育,打开“调试”以查看mongoose 实际上是如何向服务器发出语句的。然后你会看到.populate()是如何实际应用的:
mongoose.set("debug",true)