在 mongoose 中填充嵌套数组 - Node.js
Posted
技术标签:
【中文标题】在 mongoose 中填充嵌套数组 - Node.js【英文标题】:Populate nested array in mongoose - Node.js 【发布时间】:2016-10-12 05:01:26 【问题描述】:这些是我的模式(主题是父主题,包含“思想”列表):
var TopicSchema = new mongoose.Schema(
title: type: String, unique: true ,
category: String,
thoughts: [ThoughtSchema]
,
timestamps: true,
toObject: virtuals: true,
toJSON: virtuals: true
);
var ThoughtSchema = new mongoose.Schema(
text: String,
author: type: mongoose.Schema.Types.ObjectId, ref: 'User',
votes:[
_id:false,
voter: type: mongoose.Schema.Types.ObjectId, ref: 'User',
up: Boolean,
date: type: Date, default: Date.now
]
,
timestamps: true,
toObject: virtuals: true,
toJSON: virtuals: true
);
....
我正在尝试阅读该想法的作者并像这样更改我的 get Topic api:
...
var cursor = Topic.find(query).populate(
path: 'thoughts',
populate:
path: 'author',
model: 'User'
).sort(popularity : -1, date: -1);
return cursor.exec()
.then(respondWithResult(res))
.catch(handleError(res));
...
但是作者是空的..我也没有在控制台中得到任何错误。这里有什么问题?
编辑:实际上我不需要 Thought 作为模式,它在数据库中没有自己的集合。它将保存在主题中。但是为了将 timestamps 选项与想法一起使用,我需要将其内容提取到新的本地模式 ThoughtSchema。但是我现在直接在主题的想法数组中定义了thinkSchema的内容,还是不行。
Edit2:这是执行前的光标对象。不幸的是,我无法在 Webstorm 中调试,这是来自节点检查器的屏幕截图:
【问题讨论】:
@Theodore 的答案对我来说是正确的:query
的内容是什么?你有select
吗?
我上传了光标对象执行前的内容截图
【参考方案1】:
这些是架构:
var TopicSchema = new mongoose.Schema(
title: type: String, unique: true ,
category: String,
thoughts: [ThoughtSchema]
,
timestamps: true,
toObject: virtuals: true,
toJSON: virtuals: true
);
var ThoughtSchema = new mongoose.Schema(
text: String,
author: type: mongoose.Schema.Types.ObjectId, ref: 'User',
votes:[
_id:false,
voter: type: mongoose.Schema.Types.ObjectId, ref: 'User',
up: Boolean,
date: type: Date, default: Date.now
]
,
timestamps: true,
toObject: virtuals: true,
toJSON: virtuals: true
);
您是否尝试过聚合而不是填充。聚合使用$lookup
填充嵌入数据变得更加容易。试试下面的代码。
更新
Topic.aggregate([$unwind: "$thoughts", $lookup: from: 'users', localField: 'thoughts.author', foreignField: '_id', as: 'thoughts.author',$sort:popularity : -1, date: -1],function(err,topics)
console.log(topics) // `topics` is a cursor.
// Perform Other operations here.
)
解释:
$unwind:从输入文档中解构一个数组字段,为每个元素输出一个文档。
$lookup:$lookup 阶段在输入文档中的字段与“加入”集合的文档中的字段之间进行相等匹配。查找完成了人口的工作。
$lookup 的工作方式类似于
来自:这表示需要从哪个集合中填充数据。(在这种情况下为users
)。
localField :这是需要填充的本地字段。 (在这种情况下为thoughts.author
)。
foreignField :这是集合中存在的外部字段,需要从中填充数据(在这种情况下,users
集合中的_id
字段)。
as :这是您希望将连接值显示为的字段。 (这会将thoughts.author 的ID 投影为thoughts.author 文档)。
希望这行得通。
【讨论】:
“你尝试过聚合而不是填充吗?”对不起..但据我所知,聚合通常与“匹配”而不是“查找”一起使用..所以它不是填充的替代方法,但是'找到'我想..所以我不知道如何将它集成到我的代码中..聚合是否还返回一个游标对象,必须在之后执行?您能否更新我在问题中的第二个代码并写下所有行?【参考方案2】:您是否尝试过使用Model.populate?
Topic.find(query).populate('thoughts')
.sort(popularity : -1, date: -1)
.exec(function(err, docs)
// Multiple population per level
if(err) return callback(err);
Thought.populate(docs,
path: 'thoughts.author',
model: 'User'
,
function(err, populatedDocs)
if(err) return callback(err);
console.log(populatedDocs);
);
);
更新: 您可以像这样尝试deep populate:
Topic.find(query).populate(
path: 'thoughts',
populate:
path: 'author',
model: 'User'
)
.sort(popularity : -1, date: -1)
.exec(function(err, docs)
if(err) return callback(err);
console.log(docs);
);
【讨论】:
'Thought' 未导出。我也不知道如何导出多个模式...这是唯一的导出行:export default mongoose.model('Topic', TopicSchema); 您不需要将其导出,因为您将其用作嵌入式架构。在那种情况下,我确认@Theodore 的答案应该有效。你检查过你的数据库吗?对author
的引用是否正确保存?
是的.. 作者字段具有用户的 id。但我不知何故无法在 webstorm 中调试服务器端代码以查看查询的外观。我将在接下来的几天尝试调试。但是关于“思想”架构..当我按照您的建议使用 Thought.populate 时,无法编译应用程序.. 终端中出现“思想未定义”之类的东西
我建议您可以尝试另一个选项。
这正是我在我的问题中所写的【参考方案3】:
怎么样
Topic.find(query).populate('thoughts')
.sort(popularity : -1, date: -1)
.exec(function(err, docs)
// Multiple population per level
if(err) return callback(err);
Topic.populate(docs,
path: 'thoughts.author',
model: 'User'
,
function(err, populatedDocs)
if(err) return callback(err);
console.log(populatedDocs);
);
);
【讨论】:
以上是关于在 mongoose 中填充嵌套数组 - Node.js的主要内容,如果未能解决你的问题,请参考以下文章
mongoose#populate 在数组内的嵌套对象中返回 null
试图在 mongoose 中填充一个嵌套数组,抛出一个看似无关的 CastError,我不明白为啥
MongoDB Mongoose 聚合查询深度嵌套数组删除空结果并填充引用