nodejs API决定是创建还是更新

时间:2018-04-19 07:31:41

标签: javascript node.js rest api

我创建了一个nodejs API,你可以通过POST推送新的条目,如果条目已经存在,它应该更新它。

现在我遇到的问题是我从mongoose通过findOne()检查该条目是否已存在,但它不会触发更新功能。

这是代码:

通过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);
    });
  }
}

检查条目是否存在:

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

和更新功能,但这不会从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);
    });
};

提前致谢!

2 个答案:

答案 0 :(得分:0)

我会尝试以下内容。 可以使用回调而不是promises来编写相同的结构。或者不使用promisify()并将回调包装在您自己的新Promise()调用中。那就是更多的代码。

// 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;
        } );
};

答案 1 :(得分:0)

我解决了它:

  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);
    });
};

关键是findOneAndUpdate()函数中我没有设置upsert: true的选项是什么意思,如果它确实通过主机名找到一个条目,它只会创建它。