0

I'm using NodeJS with express framework and mongoose and I made town input with logic where is no input, right input and already exist input. Maybe there is better solution but this working fine:

router.post('/create', (req, res)=>{
    let errors = [];

    if (!req.body.name) {
      errors.push({message: 'Add town name!'});
    }

    if (errors.length > 0) {
      res.render('admin/towns/index', {
        errors: errors,
        name: req.body.name
      });
    } else {
      Town.findOne({name: req.body.name}).then(town=>{
        if (!town) {
          const newTown = Town({
            name: req.body.name
          });
          newTown.save().then(savedTown=>{
            req.flash('success_message', `Town ${savedTown.name} is activated`);
            res.redirect('/admin/towns');
          });
        } else {
          req.flash('error_message', 'Town name already exist!');
          res.redirect('/admin/towns');
        }
      });
    }
});

but, when I want to update, where is no input working fine, where name is new also working fine but if name exist it's shows me error:

(node:12140) UnhandledPromiseRejectionWarning: MongoError: E11000 duplicate key error collection: crm_electors.towns index: name_1 dup key: { : "Belgrade" }

router.put('/edit/:id', (req, res)=>{
    let errors = [];

    if (!req.body.name) {
      errors.push({message: 'Add town name!'});
    }

    if (errors.length > 0) {
      res.render('admin/towns/index', {
        errors: errors,
        name: req.body.name
      });
    } else {
      Town.findOne({_id: req.params.id}).then(town=>{
        if (req.body.name !== town) { // I guess this logic is wrong
          town.name = req.body.name;
          town.save().then(savedTown=>{
            req.flash('success_message', 'Town name successfully renamed');
            res.redirect('/admin/towns');
          });
        } else {
          req.flash('error_message', 'Town name already exist!');
          res.redirect('/admin/towns');
        }
      });
    }
});

I presume this logic is wrong (req.body.name !== town), so I tried req.body.name !== town.name and some more variations but no luck.

Nenad M
  • 139
  • 4
  • 16
  • Possible duplicate of [Mongoose.js: how to implement create or update?](https://stackoverflow.com/questions/13337685/mongoose-js-how-to-implement-create-or-update). I think that thread will show you the better way. – Robert Moskal Mar 17 '18 at 16:44
  • I don't know, seems to me that is not that similar to this problem or maybe I just can't see how to implement on my code...? That logic that troubles me is missing in your link. – Nenad M Mar 17 '18 at 19:42

1 Answers1

0

Mongoose works on error first callbacks where the callback has error as it's first parameter and result in the second parameter. The code you have is misleading error with result as the first parameter in your findOne callback is error which you are referencing with variable town. Thus, you need to change your code to something like:

Town.findOne({_id: req.params.id}, (err, town)=> {
      if (town) {
        //check is this new name already exist or not
        Town.find({name: req.body.name}, (err, townWithName) => {
            if(townWithName){ //if there is already a town with this name
              req.flash('error_message', 'Town name already exist!');
              res.redirect('/admin/towns');
            } else {
              town.name = req.body.name;
              town.save((err, savedTown) => {
                req.flash('success_message', 'Town name successfully renamed');
                res.redirect('/admin/towns');
              });
            }
        });
      } else {
        req.flash('error_message', 'Town with this id do not exist!!');
        res.redirect('/admin/towns');
      }
  });

Since, town in the second parameter of the callback it holds the mongoose model record. So, you can access name property from it. Furthermore, you can also handle runtime error by using that err parameter in callback by using this block of code inside callback:

if (err) {
   res.send(//some message and code);
}
Ankit Agarwal
  • 30,378
  • 5
  • 37
  • 62
  • I add err as first parameter but now this appear: (node:7708) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'name' of undefined – Nenad M Mar 17 '18 at 12:23
  • @NenadM ok then I have edited my answer. use callback function approach by removing `then` – Ankit Agarwal Mar 17 '18 at 12:24
  • Now is the same as first problem, update is good until name is duplicate. Then this: (node:4932) UnhandledPromiseRejectionWarning: MongoError: E11000 duplicate key error collection: crm_electors.towns index: name_1 dup key: { : "Belgrade" } – Nenad M Mar 17 '18 at 12:26
  • The logic was incorrect @NenadM check now. It should work – Ankit Agarwal Mar 17 '18 at 12:39
  • Can you give me a full code because now argument is missing: SyntaxError: missing ) after argument list... And I'm not quite sure where to put this: if (err) { res.send(//some message and code); } – Nenad M Mar 17 '18 at 12:43
  • I missed that in answer. Now it is corrected please check the edited code again. – Ankit Agarwal Mar 17 '18 at 12:43
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/167017/discussion-between-ankit-agarwal-and-nenad-m). – Ankit Agarwal Mar 17 '18 at 12:44