简体   繁体   中英

nodejs API decide if create or update

I created a nodejs API, where you can push new entries via POST, if the entry already exists, it should update it.

Now I have the issue that I check if the entry already exists via findOne() from mongoose, but it wont trigger the update function.

here is the code:

entry point via POST:

    exports.create_a_status = function(req, res) {
  if(read_status(req.body.hostname)){
    console.log("update")
    update(req,res)
  }    
  else{
    var new_status = new Status(req.body);
    new_status.save(function(err, status) {
      if (err)
        res.send(err);
      history.create_a_history(req.body);
      res.json(status);
    });
  }
}

check if entry exists:

const read_status = function(hostname){
  Status.findOne({hostname: hostname},function(err,status){
    console.log(hostname)
    if (status){
      console.log(status)
      return status;
    }   
    return;
  })
}

and the update function, BUT this doesnt get triggered from create_a_status() :

exports.update = function(req, res) {
    // Update a status identified by the hostname in the request
   Status.findOneAndUpdate({hostname: req.params.hostname}, req.body,{new:true})
    .then((updatedStatus) => {
      res.json(updatedStatus);
    })
    .catch((err)=>{
      res.send(err);
    });
};

Thanks in advance!

I would try something like the following. The same structure can be written with callbacks instead of promises. Or without using promisify() and wrapping the callbacks in your own new Promise() calls. It'll just be more code then.

// PROMISES VERSION
// We can import the promisify function from node util to turn our callbacks into promises.
const { promisify } = require( 'util' );
// Check if status exists.
// If exists, update it. Else create new status and new history.
// If anything throws an error, send it as the response.
const create_a_status = function( request, response ) {
Promise
    .resolve( request.body.hostname )
    .then( host => read_status( { host } ) )
    .then( status => status ? update_status( { 'hostname' : request.params.hostname, 'body' : request.body, 'new' : true } ) : new_status( request.body ) )
    .then( status => response.json( status ) );
    .catch( error => response.send( error ) );
    /* Depending on the function scopes, we might be able to omit all the x => y(x) calls.
    Promise
        .resolve( { 'host' : request.body.hostname } )
        .then( read_status )
        .then( status => status ? update_status( { 'hostname' : request.params.hostname, 'body' : request.body, 'new' : true } ) : new_status( request.body ) )
        .then( response.json );
        .catch( response.send );
    */
};
// Since we just need to return the status or error, we can just promisify the findOne method.
const read_status = promisify( Status.findOne.bind( Status ) );
// Since we just need to run the function and return, the .then().catch() in the create_a_status function will also fix this.
const update_status = promisify( Status.findOneAndUpdate.bind( Status ) );

const new_status = function( body ) {
    const status = new Status( body );
    const save = promisify( status.save.bind( status ) );
    return save
        .then( status => {
            history.create_a_history( body );
            return status;
        } );
};

I resolved it with:

  exports.update_a_status = function(req, res) {
    // Update a status identified by the hostname in the request
   Status.findOneAndUpdate({hostname: req.body.hostname}, req.body,{upsert: true, new: true, runValidators: true})
    .then((updatedStatus) => {
      res.json(updatedStatus);
    })
    .catch((err)=>{
      res.send(err);
    });
};

The point was the options in the findOneAndUpdate() function where I didnt set upsert: true what means if it doenst find an entry by hostname it will simply create it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM