我想用Node.js,Express,MongoDB和Mongoose创建一个安静的API。
架构,型号和路线如下:
// Schema
var OperatorSchema = new Schema({
name : { type: String, unique: true , required: true},
short_name : { type: String, unique:true, required: true },
});
Operator = mongoose.model('Operator', OperatorSchema);
// My Api for Operator
app.post('/api/operators', common.createOperator);
exports.createOperator = function(req, res){
Operator.create(req.body, function (err, operator) {
// If failed, return error message
if (err) {
console.log(err);
res.send(404, err)
}
else {
res.send(operator)
}
})
};
我有三个问题:
1 - 处理错误就像我发现传递给回调的错误对象具有不同的结构,具体取决于错误是来自mongoose还是mongo。
// Mongo Error:
{
"name": "MongoError",
"err": "E11000 duplicate key error index: ussdauto.operators.$name_1 dup key: { : \"OpTest\" }",
"code": 11000,
"n": 0,
"connectionId": 231,
"ok": 1
}
// Mongoose Error:
{
"message": "Validation failed",
"name": "ValidationError",
"errors": {
"short_name": {
"message": "Path `short_name` is required.",
"name": "ValidatorError",
"path": "short_name",
"type": "required"
}
}
}
我不想公开有关错误的所有细节:只有解释错误的消息就足够了,例如,不需要知道它是mongoerror还是validationError。你是如何管理它的?
2 - 第二个问题更具全局性:我将拥有多个API,每次我都需要做同样的工作:检查是否有错误,如果有一些通过API返回JSON错误消息,如果不能正常继续。如何只使用一个函数来处理错误并在任何地方使用它?
3 - 我来自一个python世界(实际上是Django),Tastypie是一个非常棒的模块,它本身就是处理所有这些东西。你知道Node.js + Express是否存在这样的模块吗?
答案 0 :(得分:0)
您可以使用名为processMongooseError(err)的函数创建一个Utils模块(或者您真的很喜欢)。然后,您可以对函数进行简单检查,以确定它是什么类型的错误,然后返回一个简单的错误消息。我在下面提到了一个我正在谈论的例子。
module.exports.processMongooseError = function(err) {
if(err.name == "MongoError") {
// mongo db error
} else if(err.name == "ValidationError") {
// mongoose error
}
}
可以在您需要的任何地方使用此模块,并解决您的第二个问题。
答案 1 :(得分:0)
如果这仍然是一个问题,我遇到了同样的问题,并使用这个mongoose插件让错误消息更加一致。 https://www.npmjs.com/package/mongoose-beautiful-unique-validation
该插件将采用mongodb错误并将其转换为像错误一样的猫鼬。
答案 2 :(得分:0)
如果您不希望在对MongoDB的POST请求后显示完整的错误响应,则可以使用Promise作为模型来链接响应,并向JSON响应的RESTFull API用户显示自定义内容。
在构建API时,我将为您提供一个示例,作为一个很好的指南:
1#模式模型./api/models/operator
const mongoose = require('mongoose');
const OperatorSchema = new Schema({
name : { type: String, unique: true , required: true},
short_name : { type: String, unique:true, required: true },
});
module.exports = mongoose.model('Operator', OperatorSchema);
2#操作员CRUD文件,(POST)进程./api/routes/operator
// let's imagine that at this point you have already set up your form somewhere in your app and you are using body-parser, you have some Headers configuration for this route.
//import the libraries to execute your CRUD
const express = require('express');
const router = express.Router();
const mongoose = require('mongoose');
const bodyParser = require('body-parser');//generates json structure from incoming form post
app.use(bodyParser.urlencoded({extended: false}));
app.use(bodyParser.json());
const Operators = require('../api/models/operators');
router.post('/api/operators', (req, res, next) => {
const operator = new Operator({
_id: new mongoose.Types.ObjectId(),
name: req.body.name, //get the form field of "operator" using body-parser
short_name: req.body.short_name // other fiels... from the Schema model
}); // Build an object to store to the database using the schema set up
// The following chain method returns a promise which you can build your custom responses for this post,
// This chain method can be used for POST GET and DELETE requests
operator.save().then(result => {
res.status(201).json({
message: "Operator Created", //
result: result // the "result" object can be filtered or you can simply return the message
});
// THE RESULT OBJECT PROPERTIES YOU CAN FILTER ON RETURN
// "result" : {
// name: "some operator name",
// short_name: "short guy",
// __v : 0,
// _id : "mongodb-id-generated"
// }
}).catch(err => {
console.log(err);
res.status(500).json({
error: err
});
});
}); // #### POSTS NEW OPERATORS
我花了相当长的时间使用此过程,并且允许开发人员将内容发布到API上是非常有效的,如果他们遇到错误,我会告诉他们如何更好地阐述他们的要求。
答案 3 :(得分:-1)
"short_name": {
"message": "Path `short_name` is required.",
此错误是因为,在您的架构中,此字段是必需的
var OperatorSchema = new Schema({
name : { type: String, unique: true , required: true},
short_name : { type: String, unique:true, required: true },
虽然您没有通过表单或邮递员应用程序提供任何输入..但您不能将所需字段留空。
我不知道告诉你什么模块导致错误的任何事情 但你可以通过查看错误来猜测。
"name": "MongoError",
"err": "E11000 duplicate key error
此错误是因为您将名称定义为唯一,但尝试再次插入名称。