如何从 Mongoose 重复错误中获取模型名称

问题描述 投票:0回答:1

在应用程序中,我定义了两个模型。第一个模型是电影模型,第二个模型是用户模型。在电影模型中,电影名称是一个唯一字段,在用户模型中,电子邮件是一个唯一字段。在“duplicateKeyErrorHandler”函数中,消息是静态的,但我需要重复电影或重复电子邮件的模型名称。

重复的错误消息写入“duplicateKeyErrorHandler”函数中。响应错误传入 duplicateKeyErrorHandler 函数。 我需要从响应错误中获取模型名称,例如 model Usermode Movie

对于重复的电影名称和重复的用户电子邮件,我收到相同的错误消息,但对于不同的模型和独特的字段,我需要不同的消息。

现在重复电影和重复用户电子邮件的错误消息是相同的:

"message": "已有一部名为《黑客帝国》的电影。请使用其他名称。",

预期的消息应该是这样的:

对于重复的电影名称

"message": "There is already a movie with name 'The Matrix'. Please use another name.",

对于重复的用户电子邮件

"message": "There is already a email with this email [email protected]. Please use another email.",

错误控制器代码是:

const CustomError = require('../utils/CustomError');

const castErrorHandler = (err) => {
    const msg = `Invalid value for ${err.path}: ${err.value}`;
    return new CustomError(msg, 400);
}

const duplicateKeyErrorHandler = (err) => {
    const msg = `There is already a movie with name ${err.keyValue.name}. Please use another name.`;
    return new CustomError(msg, 400);
}

const devErrors = (res, error) => {
    res.status(error.statusCode).json({
        status: error.status,
        message: error.message,
        stackTrace: error.stack,
        error: error
    });
}

const prodErrors = (res, error) => {
    if (error.isOperational) {
        res.status(error.statusCode).json({
            status: error.status,
            message: error.message
        });
    }
    else {
        res.status(500).json({
            status: 'error',
            message: 'Something went wrong! Please try again later.'
        });
    }
}

module.exports = (error, req, res, next) => {
    error.statusCode = error.statusCode || 500;
    error.status = error.status || 'error';

    if (process.env.NODE_ENV === "development") {
        if(error.name === "CastError") error = castErrorHandler(error);
        if(error.code === 11000) error = duplicateKeyErrorHandler(error);
        devErrors(res, error);
    } else if (process.env.NODE_ENV === "production") {
        if(error.name === "CastError") error = castErrorHandler(error);
        if(error.code === 11000) error = duplicateKeyErrorHandler(error);
        prodErrors(res, error);
    }
};

重复电子邮件字段错误响应是 - (它是用户模型):

{
    "status": "error",
    "message": "E11000 duplicate key error collection: node_practice_1.users index: email_1 dup key: { email: \"[email protected]\" }",
    "stackTrace": "MongoServerError: E11000 duplicate key error collection: node_practice_1.users index: email_1 dup key: { email: \"[email protected]\" }\n    at InsertOneOperation.execute (D:\\RND\\Node-JS\\node-practice-1\\node_modules\\mongodb\\lib\\operations\\insert.js:51:19)\n    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)\n    at async executeOperation (D:\\RND\\Node-JS\\node-practice-1\\node_modules\\mongodb\\lib\\operations\\execute_operation.js:136:16)\n    at async Collection.insertOne (D:\\RND\\Node-JS\\node-practice-1\\node_modules\\mongodb\\lib\\collection.js:155:16)",
    "error": {
        "errorResponse": {
            "index": 0,
            "code": 11000,
            "errmsg": "E11000 duplicate key error collection: node_practice_1.users index: email_1 dup key: { email: \"[email protected]\" }",
            "keyPattern": {
                "email": 1
            },
            "keyValue": {
                "email": "[email protected]"
            }
        },
        "index": 0,
        "code": 11000,
        "keyPattern": {
            "email": 1
        },
        "keyValue": {
            "email": "[email protected]"
        },
        "statusCode": 500,
        "status": "error"
    }
}

重复名称字段错误响应是 - (它是电影模型):

{
    "status": "error",
    "message": "E11000 duplicate key error collection: node_practice_1.movies index: name_1 dup key: { name: \"The Matrix\" }",
    "stackTrace": "MongoServerError: E11000 duplicate key error collection: node_practice_1.movies index: name_1 dup key: { name: \"The Matrix\" }\n    at InsertOneOperation.execute (D:\\RND\\Node-JS\\node-practice-1\\node_modules\\mongodb\\lib\\operations\\insert.js:51:19)\n    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)\n    at async executeOperation (D:\\RND\\Node-JS\\node-practice-1\\node_modules\\mongodb\\lib\\operations\\execute_operation.js:136:16)\n    at async Collection.insertOne (D:\\RND\\Node-JS\\node-practice-1\\node_modules\\mongodb\\lib\\collection.js:155:16)",
    "error": {
        "errorResponse": {
            "index": 0,
            "code": 11000,
            "errmsg": "E11000 duplicate key error collection: node_practice_1.movies index: name_1 dup key: { name: \"The Matrix\" }",
            "keyPattern": {
                "name": 1
            },
            "keyValue": {
                "name": "The Matrix"
            }
        },
        "index": 0,
        "code": 11000,
        "keyPattern": {
            "name": 1
        },
        "keyValue": {
            "name": "The Matrix"
        },
        "statusCode": 500,
        "status": "error"
    }
}
node.js mongodb mongoose mongoose-schema
1个回答
0
投票

不幸的是,唯一索引不是 mongoose 中的验证器,因此您无法用它本身传递 mongoose 自定义错误消息

但是,您已经创建了自己的自定义错误处理,因此您可以添加一些检查以查看哪个集合引发重复键错误并相应地修改错误消息。

您将看到

err.message
表明
node_practice_1.users
node_practice_1.movies
是索引的来源,因此只需检查这些:

// Create a Map to hold a reference mapping Models to Collections
const collections = new Map([
  ['User', "node_practice_1.users"],
  ['Movies', "node_practice_1.movies"],
]);

const duplicateKeyErrorHandler = (err) => {
   // Set a default as a backup
   let msg = 'Duplicate Key Error';

   // Check if its User or Movie
   if(err.message.includes(collections.get('User'))){
      msg = `There is already a user with email: ${err.keyValue.email}. Please use another email.`;
   }else if(err.message.includes(collections.get('Movies'))){
      msg = `There is already a movie with name: ${err.keyValue.name}. Please use another name.`;
   }
   return new CustomError(msg, 400);
}
© www.soinside.com 2019 - 2024. All rights reserved.