猫鼬嵌套参考种群
Mongoose nested reference population
我无法理解 mongoose populate 方法背后的一些概念。我首先采用了一种嵌入式方法,不过,由于我担心数据和不同步文档的大量开销四处走动,我尝试将范例更改为 ref
其他文档。
我的架构类似于以下内容(删除了不相关的属性):
var userSchema = mongoose.Schema({
name: {type: String, default:''},
favorites:{
users:[{type: Schema.Types.ObjectId, ref: this}],
places:[{type: Schema.Types.ObjectId, ref: PlaceSchema}]
}
});
module.exports = mongoose.model('User', userSchema);
现在我正在尝试像这样获得 User
的 favorites
:
User.findOne({_id: currentUser}).exec(function(err, user){
console.log(user);
if (err)
throw err;
if(!user){
console.log("can't find user");
}else{ // user found
user.populate('favorites.users');
user.populate('favorites.places');
// do something to the 'user.favorites' object
}
});
虽然这没有按预期工作,因为 user.favorites.users
和 user.favorites.places
都未定义。
我以为我可以像上面那样填充,但显然不是这样。从我读到的内容来看,我一定是遗漏了一些东西,表明(也许)ref
'ed 文件的模型?这个流程对我来说很新,我有点迷路了。
无论如何,我可以通过填充我的查询结果来获得 users
和 places
的数组吗?我试过 populate
与 exec
链接,但它也不起作用。有没有更好的方法来实现这个结果?
编辑:如果需要,在数据库中,User
文档显示为:
{
"_id": "56c36b330fbc51ba19cc83ff",
"name": "John Doe",
"favorites": {
"places": [],
"users": [
"56b9d9a45f1ada8e0c0dee27"
]
}
}
编辑:更多细节...我目前 storing/removing 像这样的参考 ObjectId(注意 targetID 是一个字符串):
user.favorites.users.push({ _id: mongoose.Types.ObjectId(targetID)});
user.favorites.users.pull({ _id: mongoose.Types.ObjectId(targetID)});
此外,我需要用各自的文档 和 填充 users
和 places
,我认为这在我原来的问题中可能不清楚.
尝试:
User
.findOne({_id: currentUser})
.populate('favorites.users')
.populate('favorites.places')
.exec( function (err, user) {
// user.favorites.users
// user.favorites.places
});
好吧,我通过适当关注文档(以及 @DJeanCar 的 (+1'd) help/pointers)找到了我需要的东西。
根据 Mongoose 的 docs 关于 跨多个级别填充 ,我得到了这个解决方案:
User.findOne({_id: currentUser})
.populate({path:"favorites.users", populate: "name"})
.populate({path:"favorites.places", populate: "name"})
.exec(function(err, user){
if(err)
throw err;
if(!user){
console.log("couldnt find source user");
}else{
// here, user.favorites is populated and I can do what I need with the data
}
});
此外,据我所知,如果您需要在填充后过滤所需的文档字段,您还可以在 populate()
的选项中传递 select: "field field field"
。
希望这对遇到类似问题的人有所帮助!
我无法理解 mongoose populate 方法背后的一些概念。我首先采用了一种嵌入式方法,不过,由于我担心数据和不同步文档的大量开销四处走动,我尝试将范例更改为 ref
其他文档。
我的架构类似于以下内容(删除了不相关的属性):
var userSchema = mongoose.Schema({
name: {type: String, default:''},
favorites:{
users:[{type: Schema.Types.ObjectId, ref: this}],
places:[{type: Schema.Types.ObjectId, ref: PlaceSchema}]
}
});
module.exports = mongoose.model('User', userSchema);
现在我正在尝试像这样获得 User
的 favorites
:
User.findOne({_id: currentUser}).exec(function(err, user){
console.log(user);
if (err)
throw err;
if(!user){
console.log("can't find user");
}else{ // user found
user.populate('favorites.users');
user.populate('favorites.places');
// do something to the 'user.favorites' object
}
});
虽然这没有按预期工作,因为 user.favorites.users
和 user.favorites.places
都未定义。
我以为我可以像上面那样填充,但显然不是这样。从我读到的内容来看,我一定是遗漏了一些东西,表明(也许)ref
'ed 文件的模型?这个流程对我来说很新,我有点迷路了。
无论如何,我可以通过填充我的查询结果来获得 users
和 places
的数组吗?我试过 populate
与 exec
链接,但它也不起作用。有没有更好的方法来实现这个结果?
编辑:如果需要,在数据库中,User
文档显示为:
{
"_id": "56c36b330fbc51ba19cc83ff",
"name": "John Doe",
"favorites": {
"places": [],
"users": [
"56b9d9a45f1ada8e0c0dee27"
]
}
}
编辑:更多细节...我目前 storing/removing 像这样的参考 ObjectId(注意 targetID 是一个字符串):
user.favorites.users.push({ _id: mongoose.Types.ObjectId(targetID)});
user.favorites.users.pull({ _id: mongoose.Types.ObjectId(targetID)});
此外,我需要用各自的文档 和 填充 users
和 places
,我认为这在我原来的问题中可能不清楚.
尝试:
User
.findOne({_id: currentUser})
.populate('favorites.users')
.populate('favorites.places')
.exec( function (err, user) {
// user.favorites.users
// user.favorites.places
});
好吧,我通过适当关注文档(以及 @DJeanCar 的 (+1'd) help/pointers)找到了我需要的东西。
根据 Mongoose 的 docs 关于 跨多个级别填充 ,我得到了这个解决方案:
User.findOne({_id: currentUser})
.populate({path:"favorites.users", populate: "name"})
.populate({path:"favorites.places", populate: "name"})
.exec(function(err, user){
if(err)
throw err;
if(!user){
console.log("couldnt find source user");
}else{
// here, user.favorites is populated and I can do what I need with the data
}
});
此外,据我所知,如果您需要在填充后过滤所需的文档字段,您还可以在 populate()
的选项中传递 select: "field field field"
。
希望这对遇到类似问题的人有所帮助!