【问题标题】:Populate nested array in mongoose - Node.js在 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吗?
  • 我上传了光标对象执行前的内容截图

标签: node.js mongodb mongoose


【解决方案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);
  });
});

【讨论】:

    猜你喜欢
    • 2015-03-26
    • 2020-06-07
    • 2017-03-01
    • 2019-12-06
    • 2018-06-07
    • 2019-09-23
    • 1970-01-01
    • 2016-03-01
    相关资源
    最近更新 更多