Mongoose - 使用 .populate 访问嵌套对象
Posted
技术标签:
【中文标题】Mongoose - 使用 .populate 访问嵌套对象【英文标题】:Mongoose - accessing nested object with .populate 【发布时间】:2014-08-15 16:01:44 【问题描述】:架构定义
团队.js
var TeamSchema = new Schema(
// Team Name.
name: String,
lead: String,
students :type: [
block : Number,
status : String,
student :
type: Schema.ObjectId,
ref: 'Student'
]
);
Student.js
var StudentSchema = new Schema(
name: String,
rollNo : Number,
class : Number
);
我如何填充“学生”以获得输出,如下所示:
团队
"__v": 1,
"_id": "5252875356f64d6d28000001",
"students": [
"__v": 1,
"_id": "5252875a56f64d6d28000002",
block : 1,
status : joined,
"student":
"name": Sumeeth
"rollNo" : 2
"class" : 5
,
"__v": 1,
"_id": "5252875a56f64d6d28000003",
block : 1,
status : joined,
"student":
"name": Sabari
"rollNo" : 3
"class" : 4
],
"lead": "Ratha",
这是我使用 Mongoose 获取文档的 JS:
Team.findOne(
_id: req.team._id
)
.populate('students')
.select('students')
.exec(function(err, team)
console.log(team);
var options =
path: 'students.student',
model: 'Student'
;
Student.populate(team.students,options,function(err, students)
console.log(students);
if (err)
console.log(students);
res.send(500,
message: 'Unable to query the team!'
);
else
res.send(200, students);
);
);
在我的控制台输出中,我得到以下信息:
_id: 53aa434858f760900b3f2246,
students
[ block : 1
status: 'joined'
_id: 53aa436b58f760900b3f2249 ,
block : 1
status: 'joined'
_id: 53aa436b58f760900b3f2250 ]
预期的输出是:
_id: 53aa434858f760900b3f2246,
students
[ block : 1
status: 'joined'
student :
"name": Sumeeth
"rollNo" : 2
"class" : 5
,
block : 1
status: 'joined'
student :
"name": Sabari
"rollNo" : 3
"class" : 4
]
请有人帮我解决我的错误。我应该如何使用 .populate,这样,我才能获得整个学生对象,而不仅仅是它的 id。
参考: Populate nested array in mongoose
【问题讨论】:
也许在您的问题中显示您的架构定义。 【参考方案1】:这是您想要的简化版本。
要设置的基本资料,首先是“学生”:
"_id" : ObjectId("53aa90c83ad07196636e175f"),
"name" : "Bill",
"rollNo" : 1,
"class" : 12
,
"_id" : ObjectId("53aa90e93ad07196636e1761"),
"name" : "Ted",
"rollNo" : 2,
"class" : 12
然后是“团队”集合:
"_id" : ObjectId("53aa91b63ad07196636e1762"),
"name" : "team1",
"lead" : "me",
"students" : [
"block" : 1,
"status" : "Y",
"student" : ObjectId("53aa90c83ad07196636e175f")
,
"block" : 2,
"status" : "N",
"student" : ObjectId("53aa90e93ad07196636e1761")
]
这就是你的做法:
var async = require('async'),
mongoose = require('mongoose');
Schema = mongoose.Schema;
mongoose.connect('mongodb://localhost/team');
var teamSchema = new Schema(
name: String,
lead: String,
students: [
block: Number,
status: String,
student:
type: Schema.ObjectId, ref: 'Student'
]
);
var studentSchema = new Schema(
name: String,
rollNo: Number,
class: Number
);
var Team = mongoose.model( "Team", teamSchema );
var Student = mongoose.model( "Student", studentSchema );
Team.findById("53aa91b63ad07196636e1762")
.select('students')
.exec(function(err, team)
console.log( team );
async.forEach(team.students, function(student,callback)
Student.populate(
student,
"path": "student" ,
function(err,output)
if (err) throw err;
callback();
);
,function(err)
console.log( JSON.stringify( team, undefined, 4 ) );
);
);
它会给你结果:
"_id": "53aa91b63ad07196636e1762",
"students": [
"block": 1,
"status": "Y",
"student":
"_id": "53aa90c83ad07196636e175f",
"name": "Bill",
"rollNo": 1,
"class": 12
,
"block": 2,
"status": "N",
"student":
"_id": "53aa90e93ad07196636e1761",
"name": "Ted",
"rollNo": 2,
"class": 12
]
您确实不需要“异步”模块,但我只是“习惯”。它不会“阻塞”,因此我认为它更好。
如您所见,您最初的 .populate()
调用没有做任何事情,因为它期望从数组输入中“键”关闭外部集合中的 _id
值,而这个“严格来说”并非如此因为“key”在包含“外键”的“student”上。
我确实在recent answer here 中提到了这一点,可能并不完全针对您的情况。您的搜索似乎没有找到正确的“相同答案”(尽管不完全正确)供您参考。
【讨论】:
【参考方案2】:我也遇到过同样的问题。我已使用此代码进行救援:
Team.findOne(_id: req.team._id)
.populate( path: "students.student")
.exec(function(err, team)
console.log(team);
);
【讨论】:
【参考方案3】:你想多了。让 Mongoose 为您完成工作。
Team.findOne(
_id: req.team._id
)
.populate(path:'students')
.exec(function(err, team)
console.log(team);
);
这会将学生作为文档返回,而不仅仅是 ID。
【讨论】:
【参考方案4】:TL DR
const team = await Team.findById(req.team._id)
.populate("students");
team.students = await Student.populate(team.students, path: "student");
上下文
阅读所有答案后,我测试了所有内容,只有 Neil Lun's answer 为我工作。问题是它正在通往cb地狱的道路上。所以我有点头疼,然后“重构”成一个优雅的单线。
const foundPost = await Post.findById(req.params.id)
.populate("comments")
.populate("author");
foundPost.comments = await User.populate(foundPost.comments, path: "author");
我最初的问题:
title: "Hello World",
description: "lorem",
author: /* populated */,
comments: [ // populated
text: "hi", author: /* not populated */
]
;
我的模型基本上是这样的:
User =
author,
password
;
Post =
title,
description,
author: , //ref User
comments: [] // ref Comment
;
Comment =
text,
author: // ref User
;
问题解决后的输出:
comments: [
_id: "5dfe3dada7f3570b60dd977f",
text: "hi",
author: _id: "5df2f84d4d9fcb228cd1df42", username: "jo", password: "123"
],
_id: "5da3cfff50cf094c68aa2a37",
title: "Hello World",
description: "lorem",
author:
_id: "5df2f84d4d9fcb228cd1aef6",
username: "la",
password: "abc"
;
【讨论】:
以上是关于Mongoose - 使用 .populate 访问嵌套对象的主要内容,如果未能解决你的问题,请参考以下文章
无法从 Mongoose 访问 populate()'d 对象的属性?
mongoose#populate 在数组内的嵌套对象中返回 null