【问题标题】:Casting to number from query fails. Node.js Express Mongoose从查询转换为数字失败。 Node.js Express 猫鼬
【发布时间】:2021-06-01 13:19:05
【问题描述】:

我刚刚开始使用 Node Express MongoDb 和 API 设计,我正在尝试为产品建立一个评级系统。

我添加了三个字段:

totalRating: { type: Number, required: false },
    ratings: { type: Number, required: false },
    averageRating: {
        type: Number, required: false, default: function () {
            return this.totalRating / this.ratings
        }
    },

Put 端点可以接收带有修改对象的body(CRUD 的 Ùpdate),或者接收将用于增加 totalRating 参数的 rating 参数,除以评级将计算平均评级显示。如果我直接传递一个数字值($inc: { totalRating: 5 } it works as expected The problem is that getting therating` 查询参数到一个数字会失败,所以该方法会抛出一个错误:

rating is:  { rating: '4' }
Mongoose updateProductById rating error:  CastError: Cast to Number failed for value "NaN" (type number) at path "totalRating"
    at model.Query.exec (/Volumes/ProjectsSSD/FixitServer/fixit_server_node/node_modules/mongoose/lib/query.js:4470:21)
    at model.Query.Query.findOneAndUpdate (/Volumes/ProjectsSSD/FixitServer/fixit_server_node/node_modules/mongoose/lib/query.js:3122:8)
    at Function.Model.findOneAndUpdate (/Volumes/ProjectsSSD/FixitServer/fixit_server_node/node_modules/mongoose/lib/model.js:2520:13)
    at Function.Model.findByIdAndUpdate (/Volumes/ProjectsSSD/FixitServer/fixit_server_node/node_modules/mongoose/lib/model.js:2647:32)
    at exports.updateProductById (/Volumes/ProjectsSSD/FixitServer/fixit_server_node/api/src/controllers/product.controller.js:399:13)
    at handleReturn (/Volumes/ProjectsSSD/FixitServer/fixit_server_node/node_modules/express-promise-router/lib/express-promise-router.js:24:23)
    at /Volumes/ProjectsSSD/FixitServer/fixit_server_node/node_modules/express-promise-router/lib/express-promise-router.js:64:7
    at handleReturn (/Volumes/ProjectsSSD/FixitServer/fixit_server_node/node_modules/express-promise-router/lib/express-promise-router.js:24:23)
    at /Volumes/ProjectsSSD/FixitServer/fixit_server_node/node_modules/express-promise-router/lib/express-promise-router.js:64:7
    at Layer.handle [as handle_request] (/Volumes/ProjectsSSD/FixitServer/fixit_server_node/node_modules/express/lib/router/layer.js:95:5)
    at next (/Volumes/ProjectsSSD/FixitServer/fixit_server_node/node_modules/express/lib/router/route.js:137:13)
    at exports.clientApiKeyValidation (/Volumes/ProjectsSSD/FixitServer/fixit_server_node/api/src/auth_utils.js:15:9)
    at handleReturn (/Volumes/ProjectsSSD/FixitServer/fixit_server_node/node_modules/express-promise-router/lib/express-promise-router.js:24:23)
    at /Volumes/ProjectsSSD/FixitServer/fixit_server_node/node_modules/express-promise-router/lib/express-promise-router.js:64:7
    at handleReturn (/Volumes/ProjectsSSD/FixitServer/fixit_server_node/node_modules/express-promise-router/lib/express-promise-router.js:24:23)
    at /Volumes/ProjectsSSD/FixitServer/fixit_server_node/node_modules/express-promise-router/lib/express-promise-router.js:64:7 {
  messageFormat: undefined,
  stringValue: '"NaN"',
  kind: 'Number',
  value: NaN,
  path: 'totalRating',
  reason: AssertionError [ERR_ASSERTION]: The expression evaluated to a falsy value:
  
    assert.ok(!isNaN(val))
  
      at castNumber (/Volumes/ProjectsSSD/FixitServer/fixit_server_node/node_modules/mongoose/lib/cast/number.js:28:10)
      at SchemaNumber.cast (/Volumes/ProjectsSSD/FixitServer/fixit_server_node/node_modules/mongoose/lib/schema/number.js:371:12)
      at SchemaNumber.SchemaType.applySetters (/Volumes/ProjectsSSD/FixitServer/fixit_server_node/node_modules/mongoose/lib/schematype.js:1106:12)
      at SchemaNumber.SchemaType._castForQuery (/Volumes/ProjectsSSD/FixitServer/fixit_server_node/node_modules/mongoose/lib/schematype.js:1584:15)
      at SchemaNumber.castForQuery (/Volumes/ProjectsSSD/FixitServer/fixit_server_node/node_modules/mongoose/lib/schema/number.js:425:14)
      at SchemaNumber.SchemaType.castForQueryWrapper (/Volumes/ProjectsSSD/FixitServer/fixit_server_node/node_modules/mongoose/lib/schematype.js:1551:20)
      at castUpdateVal (/Volumes/ProjectsSSD/FixitServer/fixit_server_node/node_modules/mongoose/lib/helpers/query/castUpdate.js:518:21)
      at walkUpdatePath (/Volumes/ProjectsSSD/FixitServer/fixit_server_node/node_modules/mongoose/lib/helpers/query/castUpdate.js:365:24)
      at castUpdate (/Volumes/ProjectsSSD/FixitServer/fixit_server_node/node_modules/mongoose/lib/helpers/query/castUpdate.js:95:7)
      at model.Query._castUpdate (/Volumes/ProjectsSSD/FixitServer/fixit_server_node/node_modules/mongoose/lib/query.js:4693:10)
      at castDoc (/Volumes/ProjectsSSD/FixitServer/fixit_server_node/node_modules/mongoose/lib/query.js:4723:18)
      at model.Query.Query._findAndModify (/Volumes/ProjectsSSD/FixitServer/fixit_server_node/node_modules/mongoose/lib/query.js:3602:22)
      at model.Query.<anonymous> (/Volumes/ProjectsSSD/FixitServer/fixit_server_node/node_modules/mongoose/lib/query.js:3139:8)
      at model.Query._wrappedThunk [as _findOneAndUpdate] (/Volumes/ProjectsSSD/FixitServer/fixit_server_node/node_modules/mongoose/lib/helpers/query/wrapThunk.js:16:8)
      at /Volumes/ProjectsSSD/FixitServer/fixit_server_node/node_modules/kareem/index.js:279:20
      at _next (/Volumes/ProjectsSSD/FixitServer/fixit_server_node/node_modules/kareem/index.js:103:16) {
    generatedMessage: true,
    code: 'ERR_ASSERTION',
    actual: false,
    expected: true,
    operator: '=='
  },
  valueType: 'number'
}

这是 Mongoose 架构:

const productSchema = new mongoose.Schema({
    createdOnDate: {type: Number, required: true},
    name: {type: String, required: true},
    brand: {type: String, required: true},
    price: {type: Number, required: true},
    description: {type: String, required: true},
    category: {type: String, required: true},
    city: {type: String, required: true},
    region: {type: String, required: true},
    country: {type: String, required: true},
    vendor: {type: String, required: true},
    barcode: {type: String, required: true},
    imageUrl: {type: String, required: true},
    fullImages: {type: Array, required: true},
    thumbNails: {type: Array, required: true},
    // productImage: Uint8Array,
    minimumStock: {type: Number, required: true},
    availableQuantity: {type: Number, required: true},
    soldQuantity: {type: Number, required: true},
    totalRating:{type: Number, required: false},
    ratings:{type: Number, required: false},
    averageRating:{type: Number, required: false, default: function() {
        return this.totalRating / this.ratings
      }},

},
{ timestamps: true },);

这是更新方法:

exports.updateProductById = async (req, res) => {

  const id = req.params.id;
  const rating = req.query;
  const updatedProduct = req.body;

  if (rating) {
console.log('rating is: ', rating);
const value = parseInt(rating);

    Product.findByIdAndUpdate(id,
      {
        $inc: { ratings: 1 },
        $inc: { totalRating: value }
        // $inc: { totalRating: 5 }  works perfectly
      },
      { new: true }, function (err, result) {
        if (err) {
          console.log('Mongoose updateProductById rating error: ', err);
          res.status(500).send({
            error: 'Internal error.'
          });
          return;
        }
        if (result != null) {
          console.log('Mongoose updateProductById rating: ', result);
          res.status(200).send({
            message: 'Product rating updated successfully!',
            data: result
          });
        }
        else {
          console.log('Mongoose updateProductById rating: No product found.');
          res.status(404).send({
            error: 'Product not found.'
          });

        }

      });

  } else {

    Product.findByIdAndUpdate(id, updatedProduct, { new: true }, function (err, result) {
      if (err) {
        console.log('Mongoose updateProductById error: ', err);
        res.status(500).send({
          error: 'Internal error.'
        });
      }
      if (result != null) {
        console.log('Mongoose updateProductById: ', result);
        res.status(200).send({
          message: 'Product updated successfully!',
          data: result
        });
      }
      else {
        console.log('Mongoose updateProductById: No product found.');
        res.status(404).send({
          error: 'Product not found.'
        });

      }

    });
  }
}

【问题讨论】:

  • @MohamedOraby 确实修复了它,但返回的对象没有ratings 和averageRatings。但是我现在在创建新产品时遇到错误.. 请参阅我的问题中的更新..
  • 对不起,我删除了评论并提交了答案以更好地格式化它,看不到新的更新您确定您保存了编辑?
  • @MohamedOraby 昨天确实没有保存。我现在添加了它,但总结起来,基本上现在我得到相同的数字转换错误,但现在我在计算的 averageRatings 参数上得到它,而不是在记录创建时得到它。更新现有记录也不显示ratings 或averageRating。你能看出我的架构有什么问题吗?
  • 昨天我看到你的req.query 只包含rating 所以你的averageRating 是undefined,你能告诉我你打电话的网址吗
  • 当然,我使用的是邮递员 POST,URL 是 localhost:5000/api/products/60b3f9b432043a41c6c9b144?rating=4。我还认为问题可能在于没有传递任何其他值,但是在更新方法中我传递了{$inc: { ratings: 1 },$inc: { totalRating: value }}object 但只有totalRating 增加了

标签: javascript node.js mongodb mongoose


【解决方案1】:

如果您注意到在记录 rating 时等于 {rating: "4"} 这是您的 req.query 您想要的值实际上是 req.query.rating 所以尝试类似

const rating = req.query.rating

或

const { rating } = req.query

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-01-04
    • 2021-11-06
    • 2014-04-21
    • 2017-10-24
    • 1970-01-01
    • 1970-01-01
    • 2021-04-21
    • 2016-07-27
    相关资源
    最近更新 更多