有Movie和Rank Movie 2个合集。这2个合集有引用关系。
电影模型
var mongoose = require('mongoose');
var movieSchema = new mongoose.Schema({
m_tmdb_id: {
type: Number,
unique: true,
index: true
},
m_adult: {
type: Boolean
},
m_backdrop_path: {
type: String,
},
m_title: {
type: Number
},
m_genres: {
type: Array
}
});
var MovieModel = mongoose.model('Movie', movieSchema);
module.exports = {
movie: MovieModel
}
电影排名模型
var mongoose = require('mongoose');
var rankMovieSchema = new mongoose.Schema({
movie: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Movie',
unique: true
},
rank: {
type: Number
},
count: {
type: Number
}
});
var RankMovieModel = mongoose.model('RankMovie', rankMovieSchema);
module.exports = {
rankmovie: RankMovieModel
}
我需要从具有特定标题[电影收藏条件]的收藏等级电影中选择所有项目。我怎样才能做到这一点?
最佳答案
实际上“最好”的方法是使用 .aggregate()
和 $lookup
“加入”数据并“过滤”匹配条件。这是非常有效的,因为与以 .populate()
发出“多个”查询相比,MongoDB 实际上在“服务器”本身执行所有这些操作
MovieModel.aggregate([
{ "$match": { "m_title": m_title } },
{ "$lookup": {
"from": RankMovieModel.collection.name,
"localField": "_id",
"foreignField": "movie",
"as": "rankings"
}}
])
Note: The
RankMovieModel.collection.name
is a nice way of getting the "underlying" collection name from theModel
registered with Mongoose. Since the operation is on the "server", MongoDB needs the "real collection name", so we can either "hardcode" that or just get it from the information registered on the Model itself. As is done here.
如果有“很多”的排名,那么你最好使用$unwind
,这将为每个相关的“排名”项目创建一个文档:
MovieModel.aggregate([
{ "$match": { "m_title": m_title } },
{ "$lookup": {
"from": RankMovieModel.collection.name,
"localField": "_id",
"foreignField": "movie",
"as": "rankings"
}},
{ "$unwind": "$rankings" }
])
这里还有一个特殊的处理方式,MongoDB 如何处理“加入”文档以避免违反 16MB BSON 限制。所以事实上这件特别的事情发生在 $unwind
时直接跟随 $lookup
流水线阶段:
{
"$lookup" : {
"from" : "rankmovies",
"as" : "rankings",
"localField" : "_id",
"foreignField" : "movie",
"unwinding" : {
"preserveNullAndEmptyArrays" : false
}
}
}
所以 $unwind
实际上“消失”了,而是“卷起”到 $lookup
中本身就好像这是“一个”操作。这样我们就不会直接在父文档中创建一个“数组”,在极端情况下会导致大小超过 16MB,其中包含许多“相关”项目。
如果您没有支持 $lookup
的 MongoDB ( MongoDB 3.2 minunum ) 那么你可以使用 .populate()
的“虚拟”相反(至少需要 Mongoose 4.5.0)。但请注意,这实际上对服务器执行了“两个” 查询:
首先将“虚拟”添加到架构中:
movieSchema.virtual("rankings",{
"ref": "Movie",
"localField": "_id",
"foreignField": "movie"
});
然后使用 .populate()
发出查询:
MovieModel.find({ "m_title": m_title })
.populate('rankings')
.exec()
关于javascript - 根据对子项中父项的引用查找文档,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44917336/