简体   繁体   中英

if exist update else insert with image upload

I've created following code, however i can't seem to figure out how to update the image if findOneAndUpdate find result and beside that it seems like result.save is being executed before put_form_url. How can i achieve such a function where if it exist it will update all properties and upload new image to s3 and if not it will create a new object with s3 upload.

router.post('/:id/:name/:birth/:country/:image', function(req, res, next) {

var params = req.params;
var accessHeader = req.headers;

process.env.AWS_ACCESS_KEY_ID=''
process.env.AWS_SECRET_ACCESS_KEY=''
AWS.config.region = 'eu-west-1';
var s3 = new AWS.S3();


User.findOneAndUpdate({"_id": params.id},  {$set:{"name": params.name, "birthday": params.birth, "country": params.country}}, {new: true}, function(error, result) {
  if (!error) {
      // If the document doesn't exist
      if (!result) {
          // Create it

          put_from_url(params.image, new Date().toString, function(err, res) {

            result = new User({
              _id: params.id,
              name: params.name,
              birthday: new Date(params.birth),
              country: params.country,
              image: "url" + params.id
            });
          });


      }
      // Save the document
      result.save(function(error) {
          if (!error) {
              res.json({ message: 'User created!' });
          } else {
              res.send(err);
          }
      });
    }
  });




});

Upload function

function put_from_url(url, key, callback) {
    request({
        url: url,
        encoding: null
    }, function(err, res, body) {
        if (err)
            return callback(err, res);

        uploader.putObject({
            Bucket: "",
            Key: "/" + key,
            ContentType: res.headers['content-type'],
            ContentLength: res.headers['content-length'],
            Body: body // buffer
        }, callback);
    })
}

Okay, it seems you have two parts of the question.

  1. how do you achieve it to store an image if there is no user and update if there is already a user.

So in either case you have to store the image, so why not to do something like either first you update the image and then you update/insert the user or do the vice-versa. personally I would choose the former.

router.post('/:id/:name/:birth/:country/:image', function(req, res, next) {

var params = req.params;
var accessHeader = req.headers;

process.env.AWS_ACCESS_KEY_ID=''
process.env.AWS_SECRET_ACCESS_KEY=''
AWS.config.region = 'eu-west-1';
var s3 = new AWS.S3();

     put_from_url(params.image, params.id, function(err, res) {

            result = new User({
              _id: params.id,
              name: params.name,
              birthday: new Date(params.birth),
              country: params.country,
              image: "url" + params.id
            });
            // Save the document
            result.save(function(error) {
               if (!error) {
                  res.json({ message: 'User created!' });
                } else {
                  res.send(err);
                }
            });
          });

few notes is that for key you were using date but I just used id so that it can be updated with new image later on. s3 object can be used and updated by unique key. if you want to do something like keep an old copy of images, you better use key like params.id/(new Date().toString) so old images would not be overwritten

Secondly, save function inherently updates if the object is there based on _id else it creates a new one.

  1. it seems like result.save is being executed before put_form_url

It surely will, javascript is inherently asynchronous which means if one code is taking too long, it will execute next statement. when you make a call to s3, its an I/O call which will try to upload an image to s3 and it will be handled, meanwhile your next line of code which in your case was result.save would be executed.

There are two ways. i> wrap the next call in the callback of previous call. and far better and superior ii> use promises.

Promises are sort of future event where you can tell upload to s3 then save into DB.

Promises have little learning curve, but it's great, clean and really helpful. q is one such promise module.

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