node.js - 在预验证中间件之后创建或更新字段?

标签 node.js mongodb mongoose

我正在尝试创建一个将触发预验证中间件的“findOneAndUpdate”查询。

当请求正文中未提供时,需要这些中间件来验证给定坐标并创建“id”字段(是的,不是“_id”字段)。

正如您在下面看到的(请参阅代码中的注释),我很接近,但不明白为什么 mongo 抛出的错误是重复键多样性。

也许 promises 不是去这里的方式,尽管它们让我能够完成比链式 pre 中间件更多的事情。

这是我的 Express 路线:

/* POST /geolocs */
router.post('/', function(req, res, next) {

  Geoloc.create(req.body, function(err, post) {
    if (err) return next(err);

    res.status(201).json(post);
  });
});

这是我的架构:

var GeolocSchema = new mongoose.Schema({
  id: {
    type: String,
    required: true,
    unique: true
  },
  location: {
    type: {
      type: String,
      default: 'Point',
      required: true
    },
    coordinates: {
      type: [Number],
      required: true
    }
  },
  count: Number
});

GeolocSchema.index({
  location: '2dsphere'
});

预验证中间件:

// Before validation, check given coordinates for errors.
GeolocSchema.pre('validate', function(next) {
  coord = this.location.coordinates
  if (this.location.type && coord) {
    if (Array.isArray(coord) && coord.length === 2) {
      lat = coord[1];
      lon = coord[0];
      if ((-90 <= lat && lat <= 90) && (-180 <= lat && lat <= 180)) next();
    }
  }
  var err = new Error('...'); // Long error text, irrelevant here
  err.status = 400;
  next(err);
});

// Then, if no 'id' is given, create it.
GeolocSchema.pre('validate', function(next) {
  if (!this.id) {
    strLat = this.location.coordinates[1].toFixed(3).replace('.', '_');
    strLon = this.location.coordinates[0].toFixed(3).replace('.', '_');
    this.id = strLat + '-' + strLon;
  }
  next();
});

我希望能够做的是在上面的下面添加以下内容:

// Here, using the validate or save hook doesn't change anything.
GeolocSchema.pre('validate', function(next) {
  var prom = Geoloc.findOne({
    'id': {
      $eq: this.id
    }
  }).exec();

  prom.then((err, geoloc) => {  // Arrow function here to access 'this'
    if (err) next(err);
    // If no geoloc was found, go ahead and save.
    if (!geoloc) next();

    // Else, update to increment the count (THIS WORKS).
    return Geoloc.update({'id': this.id}, {$inc: {count: 1}}).exec();

  }).then((toto) => {    
    // This doesn't work, the error thrown by mongo is a duplicate key error (E11000).
    if (toto) next(new Error('204'));
    else next(new Error("Something that shouldn't happen, happened..."));
  });
});

最佳答案

问题是 pre()post() 中间件 savevalidate 没有被执行通过 update()findOneAnUpdate() 等。它在 docs 中提到还有一个 GitHub issue

但是,有 pre('findOneAndUpdate')post('findOneAndUpdate') Hook 可用(不确定 update 的 Hook 是否可用> 作品)。

希望对你有帮助。

关于node.js - 在预验证中间件之后创建或更新字段?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41717602/

相关文章:

node.js - 是否可以一次搜索多个 Mongoose 模型?

node.js - 如何在 Mongoose 中找到基于 and 条件的模型的不同字段?

node.js - 无法将 UTF-8 编码的字符串从 Android 发送到 Node.js

mongodb - LoopBack4 MongoDB 自动递增自定义 ID

node.js - 来自 fs.createReadStream 的 ENOENT 是不可捕获的吗?

javascript - passport.js 中的 Date.now 无法完成

mongodb - 无法在 Mongoose 中保存文档 - 所需的验证器因路径错误而失败

javascript - 无法从单个项目中的不同文件插入到 MongoDB 实例

javascript - 使用 Nodemailer 发布 JSON 来发送电子邮件要么发送邮件,但挂起或引发错误

node.js - 为什么我在云函数中使用不同的 Node 运行时版本?