包装mongoose验证错误的最佳方法

时间:2017-09-29 03:40:07

标签: node.js mongodb mongoose error-handling microservices

我们知道mongoose为我们提供了一种简单的验证方法。但是假设您正在使用express + mongoose来构建微服务;一些客户(可能是网络应用程序,移动应用程序等)需要消费它。

通常,我更喜欢用简单的错误代码和消息来回复JSON。在大多数情况下,客户可以根据他们向用户显示的语言创建自己的消息。

默认情况下,如果我们从mongoose捕获错误,我们可以获得JSON响应,例如:

JSON响应

{
    "errors": {
        "price": {
            "message": "Path `price` (-1) is less than minimum allowed value (0).",
            "name": "ValidatorError",
            "properties": {
                "min": 0,
                "type": "min",
                "message": "Path `{PATH}` ({VALUE}) is less than minimum allowed value (0).",
                "path": "price",
                "value": -1
            },
            "kind": "min",
            "path": "price",
            "value": -1,
            "$isValidatorError": true
        },
        "code": {
            "message": "Product with given code already exists",
            "name": "ValidatorError",
            "properties": {
                "type": "user defined",
                "message": "Product with given code already exists",
                "path": "code",
                "value": "p-1000"
            },
            "kind": "user defined",
            "path": "code",
            "value": "p-1000",
            "$isValidatorError": true
        }
    },
    "_message": "Product validation failed",
    "message": "Product validation failed: price: Path `price` (-1) is less than minimum allowed value (0)., code: Product with given code already exists",
    "name": "ValidationError"
}

Restful Api Controller

exports.createOne = async(function* list(req, res) {
  try {
    const product = new Product(req.body)
    const newProduct = yield product.save()
    res.json(newProduct)
  } catch (err) {
    res.status(400).json(err)
  }
})

Model Product.js

const mongoose = require('mongoose')

const Schama = mongoose.Schema

const minlength = [5, 'The value of `{PATH}` (`{VALUE}`) is shorter than the minimum allowed length ({MINLENGTH}).'];

const ProductSchema = new Schama({
  code: { type: String, required: true, minlength, index: true, unique: true, trim: true, lowercase: true },
  name: { type: String, required: true, trim: true },
  price: { type: Number, required: true, min: 0, max: 100000 },
  categories: [String],
})

ProductSchema.path('code').validate(function uniqueEmail(code, fn) {
  const Product = mongoose.model('Product')
  // Check only when it is a new Product or when code field is modified
  if (this.isNew || this.isModified('code')) {
    Product.find({ code }).exec((err, products) => {
      fn(!err && products.length === 0)
    })
  } else fn(true)
}, 'Product with given code already exists')

ProductSchema.statics = {


  /**
   * List products
   *
   * @param {Object} options
   * @api private
   */

  pageList: function pageList(conditions, index, size) {
    const criteria = conditions || {}
    const page = index || 0
    const limit = size || 30
    return this.find(criteria)
      .populate('user', 'name username')
      .sort({ createdAt: -1 })
      .limit(limit)
      .skip(limit * page)
      .exec()
  },
}

mongoose.model('Product', ProductSchema)

我的期望

我正在尝试包装错误消息,以使其对消费者来说很简单。 它可能像:

{
    "errors": [
        {
            "message": "Path `price` (-1) is less than minimum allowed value (0).",
            "code": "100020"
        },
        {
            "message": "Product with given code already exists",
            "code": "100021"
        }
    ],
    "success": false
}
  

将在api文档上维护代码和相应的消息。该消息通常对于消费者理解代码是有用的,并且消费者(例如web客户端)可以根据代码创建他们自己的消息,例如法国消息并向最终用户显示。

如何利用mongoose的valiation来实现这一目标?也许我可以循环erros的属性并使用${path}-${kind}组合代码。

我知道在大多数情况下,客户端应该在调用apis之前进行验证。但必须有一些情况下,API必须抛出错误。

对此有何想法?

0 个答案:

没有答案