【发布时间】: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