Mongoose 填充子子文档
Posted
技术标签:
【中文标题】Mongoose 填充子子文档【英文标题】:Mongoose populate sub-sub document 【发布时间】:2014-08-16 09:19:40 【问题描述】:我的 MongoDB 中有这个设置
项目:
title: String
comments: [] // of objectId's
评论:
user: ObjectId()
item: ObjectId()
comment: String
这是我的 Mongoose 架构:
itemSchema = mongoose.Schema(
title: String,
comments: [ type: Schema.Types.ObjectId, ref: 'comments' ],
);
Item = mongoose.model('items', itemSchema);
commentSchema = mongoose.Schema(
comment: String,
user: type: Schema.Types.ObjectId, ref: 'users' ,
);
Comment = mongoose.model('comments', commentSchema);
这是我与 cmets 一起获得物品的地方:
Item.find().populate('comments').exec(function(err, data)
if (err) return handleError(err);
res.json(data);
);
如何使用其各自的用户填充 cmets 数组?既然每条评论都有一个用户ObjectId()?
【问题讨论】:
您可以分两个阶段进行操作,如该问题的已接受答案所示:***.com/questions/19222520/… 【参考方案1】:另一种方法(更简单):
Item
.find()
.populate(
path: 'comments',
populate: path: 'user',
model: 'users'
)
.exec(function(err, data)
if (err) return handleError(err);
res.json(data);
);
【讨论】:
感谢您的回答。你的回答很棒。 顺便说一下,不需要第一次填充 这是在 4 小时的研究中对我有用的独特答案,恭喜! > 更容易并帮助解决我的问题!非常感谢!【参考方案2】:作为对结果对象调用填充的完整示例:
Item.find().populate("comments").exec(function(err,data)
if (err) return handleError(err);
async.forEach(data,function(item,callback)
User.populate(item.comments, "path": "user" ,function(err,output)
if (err) throw err; // or do something
callback();
);
, function(err)
res.json(data);
);
);
从模型调用的表单中对.populate()
的调用将文档或数组作为其第一个参数。因此,您循环遍历每个项目的返回结果,并以这种方式在每个“cmets”数组上调用填充。 “路径”告诉函数它匹配的是什么。
这是使用 forEach 的“异步”版本完成的,因此它是非阻塞的,但通常在所有操作之后,响应中的所有项目不仅填充有 cmets,而且 cmets 本身具有相关的“用户”详情。
【讨论】:
这很有帮助。谢谢! @neil Lunn 我遇到了错误。你能帮我解决这个问题吗? async.forEach(data,function(item,callback) ^ ReferenceError: async is not defined @FarheenP - 使用npm install async
安装它,然后您可以通过var async = require('async');
包含它。见github.com/caolan/async【参考方案3】:
更简单
Item
.find()
.populate(
path: 'comments.user',
model: 'users'
)
.exec(function(err, data)
if (err) return handleError(err);
res.json(data);
);
【讨论】:
【参考方案4】:要添加人们可能希望使用的最终方法来仅从子文档中选择特定字段,您可以使用以下“选择”语法:
Model.findOne( _id: 'example' )
.populate(
path: "comments", // 1st level subdoc (get comments)
populate: // 2nd level subdoc (get users in comments)
path: "user",
select: 'avatar name _id'// space separated (selected fields only)
)
.exec((err, res) =>
// etc
);
【讨论】:
【参考方案5】:填充子子文档并从多个模式中填充
ProjectMetadata.findOne(id:req.params.prjId)
.populate(
path:'tasks',
model:'task_metadata',
populate:
path:'assigned_to',
model:'users',
select:'name employee_id -_id' // to select fields and remove _id field
)
.populate(
path:'client',
model:'client'
)
.populate(
path:'prjct_mgr',
model:'users'
)
.populate(
path:'acc_exec',
model:'users'
)
.populate(
path:'prj_type',
model:'project_type'
).then ( // .. your thing
或者你可以按照以下方式进行..
ProjectMetadata.findOne(id:req.params.prjId)
.populate(
[
path:'tasks',
model:TaskMetadata,
populate:[
path:'assigned_to',
model:User,
select:'name employee_id'
,
path:'priority',
model:Priority,
select:'id title'
],
select:"task_name id code assign_to stage priority_id"
,
path:'client',
model:Client,
select:"client_name"
,
path:'prjct_mgr',
model:User,
select:"name"
,
path:'acc_exec',
model:User,
select:'name employee_id'
,
path:'poc',
model:User,
select:'name employee_id'
,
path:'prj_type',
model:ProjectType,
select:"type -_id"
])
当我必须获取同一个父级的多个子子文档时,我发现第二种方法(使用数组)更有用。
【讨论】:
【参考方案6】:我用这个:
.populate(
path: 'pathName',
populate: [
path: 'FirstSubPathName',
model: 'CorrespondingModel',
,
path: 'OtherSubPathName',
model: 'CorrespondingModel',
,
path: 'AnotherSubPathName',
model: 'CorrespondingModel',
,
]
);
这是我发现的更简单的方法。我希望能提供帮助。 :)
【讨论】:
【参考方案7】:试试看吧 查找项目并获取与项目相关的填充任务和特定任务用户查找
db.Project.find()
.populate(
path: 'task',
populate: path: 'user_id'
)
.exec(async(error,results)=>
)
【讨论】:
欢迎来到 SO!尝试格式化您的答案以获得更好的可读性,这将有助于其他人遇到相同的问题。【参考方案8】:查看下面的屏幕截图。这东西就像魅力一样!
【讨论】:
Please don't post screenshots of text。它们无法被搜索或复制,并且可用性差。相反,将代码作为文本直接粘贴到您的问题中。如果选择它并单击
按钮或 Ctrl+K 代码块将缩进四个空格,这将导致其呈现为代码。【参考方案9】:
这对我有用:
即不需要模型
.populate(
path: 'filters',
populate:
path: 'tags',
populate:
path: 'votes.user'
)
.populate(
path: 'members'
)
【讨论】:
以上是关于Mongoose 填充子子文档的主要内容,如果未能解决你的问题,请参考以下文章