在返回之前更新mongoose文档

时间:2017-02-27 10:40:08

标签: node.js mongodb express asynchronous mongoose

我想在返回的mongoose查询文档中添加一个属性。这个属性也是一个猫鼬查询

Buildung.find({_id: {$in: user.favorites}}, function (err, buildungs) {
      if (err) { return res.status(400).json({error: err}); }

      const mbuildungs = buildungs.map(buildung => {

        let buildungObject = buildung.toObject();

        const now = new Date();
        Time.findOne({buildung: buildung._id, validFrom: { $lte: Date.parse(now) }}, null,
          {sort: {validFrom: -1}}, (err, time)=> {

            buildungObject.time = time;
          });

        return buildungObject;

      });

      return res.status(200).json({buildungs: mbuildungs})
});

应该返回修改后的对象,但它不会将属性time添加到结果中。

我也尝试使用回调函数,但我可以解决问题,我想实现。

更新

1)架构
// Time
const TimeSchema = new mongoose.Schema({
validFrom: {type: Date, required: true},
....
building: {type: Schema.Types.ObjectId, ref: 'Building', index: true, required: true}

// Building
const BuildingSchema = new mongoose.Schema({
  name: {type: String, required: true},
  .....
  // no relation to timeSchma
})

1 个答案:

答案 0 :(得分:2)

您可以在代码中修复一些内容!

  1. 无法在地图内调用异步函数。您需要某种方式来聚合每个findOne结果 - 最简单的方法是使用async模块。但是,我个人推荐一种基于Promise的解决方案,因为它看起来更干净。

  2. Mongoose返回自己的对象(称为MongooseDocument),该对象使用许多特定于Mongoose的函数进行修饰,这使得返回对象的行为不同。要解决此问题,请使用lean()。这将返回一个可以像任何其他JS对象一样自由修改的普通对象。使用lean()还具有huge performance improvements

  3. 的额外优势

    我已将这些更改包含在您的代码中 -

    const async = require('async');
    
    function findBuildungTime(buildung, done) {
        const now = new Date();
        Time.findOne({ buildung: buildung._id, validFrom: { $lte: Date.parse(now) } }, null, { sort: { validFrom: -1 } })
            .lean()
            .exec((err, time) => {
                buildung.time = time;
                return done(err, buildung);
            });
    }
    
    Buildung.find({ _id: { $in: user.favorites } })
        .lean()
        .exec((err, buildungs) => {
            if (err) {
                return res.status(400).json({ error: err });
            }
            async.map(buildungs, findBuildungTime, (err, results) => {
                return res.status(200).json({ buildungs: results })
            });
        });