Javascript 使用mongoose保存新数据时避免重复

Javascript 使用mongoose保存新数据时避免重复,javascript,mongodb,mongoose,ecmascript-6,error-handling,Javascript,Mongodb,Mongoose,Ecmascript 6,Error Handling,我正在开发一个可以将目的地保存到Mongo DB的应用程序。当试图保存数据库中已经存在的目标时,我想抛出一个自定义错误。Mongoose阻止了这种情况的发生,但我需要清晰和用户友好的错误处理 // post a new destination router.post('/', (req, res) => { const newCity = new cityModel( { name: req.body.name, country:

我正在开发一个可以将目的地保存到Mongo DB的应用程序。当试图保存数据库中已经存在的目标时,我想抛出一个自定义错误。Mongoose阻止了这种情况的发生,但我需要清晰和用户友好的错误处理

// post a new destination

router.post('/',
  (req, res) => {
    const newCity = new cityModel(
      {
        name: req.body.name,
        country: req.body.country
      }
    )
    newCity.save()
      .then(city => {
        res.send(city)
      })
      .catch(err => {
        res.status(500).send('Server error')
      })
  });

在保存新目的地之前,您可以使用
findOne
方法检查是否存在文档,如果存在,您可以返回自定义错误

router.post(“/”,异步(req,res)=>{
const{name,country}=req.body;
试一试{
const existingDestination=wait cityModel.findOne({name,country});
如果(现有目的地){
返回res.status(400).send(“目的地已存在”);
}
设newCity=newcitymodel({name,country});
newCity=等待newCity.save();
秘书长(城市);
}捕捉(错误){
控制台日志(err);
res.status(500).send(“服务器错误”);
}
});

请注意,我猜重复发生在相同的国家和名称存在时。如果它不是您想要的,您可以在findOne中更改查询。

在保存新目标之前,您可以使用
findOne
方法检查是否存在文档,如果存在,您可以返回自定义错误

router.post(“/”,异步(req,res)=>{
const{name,country}=req.body;
试一试{
const existingDestination=wait cityModel.findOne({name,country});
如果(现有目的地){
返回res.status(400).send(“目的地已存在”);
}
设newCity=newcitymodel({name,country});
newCity=等待newCity.save();
秘书长(城市);
}捕捉(错误){
控制台日志(err);
res.status(500).send(“服务器错误”);
}
});
请注意,我猜重复发生在相同的国家和名称存在时。如果它不是您想要的,您可以在findOne中更改查询。

因为您已经创建了索引,所以当您尝试写入副本时,结果将是:

WriteResult({
   "nInserted" : 0,
   "writeError" : {
      "code" : 11000,
      "errmsg" : "E11000 duplicate key error index: test.collection.$a.b_1 dup key: { : null }"
   }
})
您的代码:

module.exports = {
    DUPLICATE_DESTINATION_MSG: 'Destionation values already exists',
    DUPLICATE_DESTINATION_CODE: 4000
} 
//post a new destination
const constants = require('path to constants File');
router.post('/',
    (req, res) => {
        const newCity = new cityModel(
            {
                name: req.body.name,
                country: req.body.country
            }
        )
        try {
            let city = await newCity.save();
            res.send(city)
        } catch (error) {
            if (error.code == 11000) res.status(400).send(`Destination - ${req.body.name} with country ${req.body.country} already exists in system`);
            /* In case if your front end reads your error code &
                it has it's own set of custom business relates messages then form a response object with code/message & send it. 
            if (error.code == 11000) {
                let respObj = {
                    code: constants.DUPLICATE_DESTINATION_CODE,
                    message: constants.DUPLICATE_DESTINATION_MSG
                }
                res.status(400).send(respObj);
            } */
        }
        res.status(500).send('Server error');
    })
常量文件:

module.exports = {
    DUPLICATE_DESTINATION_MSG: 'Destionation values already exists',
    DUPLICATE_DESTINATION_CODE: 4000
} 
//post a new destination
const constants = require('path to constants File');
router.post('/',
    (req, res) => {
        const newCity = new cityModel(
            {
                name: req.body.name,
                country: req.body.country
            }
        )
        try {
            let city = await newCity.save();
            res.send(city)
        } catch (error) {
            if (error.code == 11000) res.status(400).send(`Destination - ${req.body.name} with country ${req.body.country} already exists in system`);
            /* In case if your front end reads your error code &
                it has it's own set of custom business relates messages then form a response object with code/message & send it. 
            if (error.code == 11000) {
                let respObj = {
                    code: constants.DUPLICATE_DESTINATION_CODE,
                    message: constants.DUPLICATE_DESTINATION_MSG
                }
                res.status(400).send(respObj);
            } */
        }
        res.status(500).send('Server error');
    })
代码:

module.exports = {
    DUPLICATE_DESTINATION_MSG: 'Destionation values already exists',
    DUPLICATE_DESTINATION_CODE: 4000
} 
//post a new destination
const constants = require('path to constants File');
router.post('/',
    (req, res) => {
        const newCity = new cityModel(
            {
                name: req.body.name,
                country: req.body.country
            }
        )
        try {
            let city = await newCity.save();
            res.send(city)
        } catch (error) {
            if (error.code == 11000) res.status(400).send(`Destination - ${req.body.name} with country ${req.body.country} already exists in system`);
            /* In case if your front end reads your error code &
                it has it's own set of custom business relates messages then form a response object with code/message & send it. 
            if (error.code == 11000) {
                let respObj = {
                    code: constants.DUPLICATE_DESTINATION_CODE,
                    message: constants.DUPLICATE_DESTINATION_MSG
                }
                res.status(400).send(respObj);
            } */
        }
        res.status(500).send('Server error');
    })
由于您已经创建了索引,当您尝试写入副本时,结果将是:

WriteResult({
   "nInserted" : 0,
   "writeError" : {
      "code" : 11000,
      "errmsg" : "E11000 duplicate key error index: test.collection.$a.b_1 dup key: { : null }"
   }
})
您的代码:

module.exports = {
    DUPLICATE_DESTINATION_MSG: 'Destionation values already exists',
    DUPLICATE_DESTINATION_CODE: 4000
} 
//post a new destination
const constants = require('path to constants File');
router.post('/',
    (req, res) => {
        const newCity = new cityModel(
            {
                name: req.body.name,
                country: req.body.country
            }
        )
        try {
            let city = await newCity.save();
            res.send(city)
        } catch (error) {
            if (error.code == 11000) res.status(400).send(`Destination - ${req.body.name} with country ${req.body.country} already exists in system`);
            /* In case if your front end reads your error code &
                it has it's own set of custom business relates messages then form a response object with code/message & send it. 
            if (error.code == 11000) {
                let respObj = {
                    code: constants.DUPLICATE_DESTINATION_CODE,
                    message: constants.DUPLICATE_DESTINATION_MSG
                }
                res.status(400).send(respObj);
            } */
        }
        res.status(500).send('Server error');
    })
常量文件:

module.exports = {
    DUPLICATE_DESTINATION_MSG: 'Destionation values already exists',
    DUPLICATE_DESTINATION_CODE: 4000
} 
//post a new destination
const constants = require('path to constants File');
router.post('/',
    (req, res) => {
        const newCity = new cityModel(
            {
                name: req.body.name,
                country: req.body.country
            }
        )
        try {
            let city = await newCity.save();
            res.send(city)
        } catch (error) {
            if (error.code == 11000) res.status(400).send(`Destination - ${req.body.name} with country ${req.body.country} already exists in system`);
            /* In case if your front end reads your error code &
                it has it's own set of custom business relates messages then form a response object with code/message & send it. 
            if (error.code == 11000) {
                let respObj = {
                    code: constants.DUPLICATE_DESTINATION_CODE,
                    message: constants.DUPLICATE_DESTINATION_MSG
                }
                res.status(400).send(respObj);
            } */
        }
        res.status(500).send('Server error');
    })
代码:

module.exports = {
    DUPLICATE_DESTINATION_MSG: 'Destionation values already exists',
    DUPLICATE_DESTINATION_CODE: 4000
} 
//post a new destination
const constants = require('path to constants File');
router.post('/',
    (req, res) => {
        const newCity = new cityModel(
            {
                name: req.body.name,
                country: req.body.country
            }
        )
        try {
            let city = await newCity.save();
            res.send(city)
        } catch (error) {
            if (error.code == 11000) res.status(400).send(`Destination - ${req.body.name} with country ${req.body.country} already exists in system`);
            /* In case if your front end reads your error code &
                it has it's own set of custom business relates messages then form a response object with code/message & send it. 
            if (error.code == 11000) {
                let respObj = {
                    code: constants.DUPLICATE_DESTINATION_CODE,
                    message: constants.DUPLICATE_DESTINATION_MSG
                }
                res.status(400).send(respObj);
            } */
        }
        res.status(500).send('Server error');
    })

我不会对此进行争论,也不会说不应该这样做,但一般来说,您不会故意将副本写入DB,在许多正确的副本中可能只有极小的机会,但这样做需要对进入DB的所有Unique进行两次DB调用。“唯一索引”的目的不仅限于避免意外创建重复项,还用于减少应用程序进行的此类预检查。@ZoltanSzokodi为什么改变主意?这个答案更清晰。另外一个答案也有一些问题,我在那个答案中对此进行了评论。我不会争论,也不会说不应该这样做,但一般来说,你不会有意地将副本写入DB,很多正确的副本中可能只有极小的机会,但这样做的话,你需要对进入DB的所有unique进行两次DB调用。“唯一索引”的目的不仅限于避免意外创建重复项,还用于减少应用程序进行的此类预检查。@ZoltanSzokodi为什么改变主意?这个答案更清晰。其他答案有我在该答案中评论过的问题。如果还有其他唯一索引,那么这段代码会误导用户目标已经存在。@SuleymanSah:如果输入请求有其他具有唯一索引的字段,这是可能的,在这种情况下,您可以读取dup密钥名称的消息,并仅在代码与11000匹配(并非所有其他错误)后才对其进行匹配,这将是仅在负面情况下的多个检查级别,也仅在输入具有多个唯一性的字段时才进行检查!!这将使您的答案更加复杂。@SuleymanSah:我不认为,我不会担心在消极的情况下编写代码,这些代码会偶尔执行一次,而不是检查每个请求-如果您知道您的请求和响应,则不需要这样做:-!!!比如说,即使你做了预检查,你也必须写“如果”块来检查所有字段,但如果你在错误情况下做了相同的检查,你可能只会像一次检查一样传递错误消息……虽然它可以工作,但我想知道它会使哪些场景变得复杂?如果还有其他唯一的索引呢,然后,此代码将误导用户目标已经存在。@SuleymanSah:如果输入请求中有其他具有唯一索引的字段,则可能会出现这种情况,在这种情况下,您可以读取dup密钥名称的消息,并仅在代码与11000匹配后才对其进行匹配(并非所有其他错误),这将是一个更高层次的检查,只有在负面的情况下,也只有当输入字段有多个唯一!!这将使您的答案更加复杂。@SuleymanSah:我不认为,我不会担心在消极的情况下编写代码,这些代码会偶尔执行一次,而不是检查每个请求-如果您知道您的请求和响应,则不需要这样做:-!!!比方说,即使你做了预检查,你也必须写“如果”块来检查所有字段,但如果你在错误情况下做了相同的检查,你可能只会像一次检查一样传递错误消息……虽然它可以工作,但我想知道它会使哪些场景变得复杂?