在mongoose中填充嵌套数组 - Node.js

时间:2016-06-11 08:23:39

标签: node.js mongodb mongoose

这些是我的架构(主题是父级,包含一个'思想的列表):

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}
});

....

我正在尝试阅读这位思想的作者并改变我的获取主题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));
...

但是作者是null ..我也没有在控制台中得到任何错误。这有什么不对?

编辑:实际上我不需要思想作为架构,它在数据库中没有自己的集合。它将保存在主题中。但是为了在思想中使用 timestamps 选项,我需要将其内容提取到新的本地模式ThoughtSchema。但是我现在已经在思想主题数组中直接定义了thinkSchema的内容,它仍然不起作用。

Edit2:这是执行前的光标对象。不幸的是我无法在Webstorm中调试,这是节点检查员的截图:

enter image description here

3 个答案:

答案 0 :(得分:0)

怎么样

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);
  });
});

答案 1 :(得分:0)

您是否尝试使用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);
});

答案 2 :(得分:0)

这些是模式:

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 :这是需要填充数据的集合中的外部字段(在此方案中_id集合中的users字段)。

as :这是您要将联接值显示为的字段。 (这将投射ideas.author的id作为ideas.author文件)。

希望这有效。