在 Loopback 上,如何在使用从访问令牌获取的 user_id 时执行 Upsert 事件?

On Loopback, how to perform an Upsert event while using the user_id obtained from access token?

假设您有两个表:CARSVOTES

现在您想让您的用户在汽车中投票。他们可以投票给一辆新车或改变他们之前的投票,但没有用户可以两次投票给相同的护理。

VOTE-MODEL

car_id

user_id

vote_value

您将如何为该模型设置更新插入过程?请记住,Upsert 方法不接受远程挂钩(在保存之前),这将阻止您从访问令牌中获取 user_id


以下是我尝试过但没有奏效的一些方法:

尝试 1

'use strict';
module.exports = function (Votes) {
  Votes.observe('before save', function setAutoData(context, next) {
    if (context.instance) {
      if (context.isNewInstance) {
        if (context.options.accessToken) {
          context.instance.user_id = context.options.accessToken.userId;
          Votes.upsertWithWhere({
            where: {
              car_id: context.instance.car_id,
              user_id: context.instance.user_id
            }
          }, context.instance, function (err, cb) {
            if (err) return next(err);
            console.log('cb', cb);
          });
        }
      }
    }
  });
};

尝试 2

'use strict';

module.exports = function(Votes) {

  Votes.observe('before save', function setAutoData(context, next) {
    if (context.instance) {
        if(context.isNewInstance) {

          if (context.options.accessToken) {

            context.instance.user_id = context.options.accessToken.userId;

            Votes.find({
              where: {
                car_id: context.instance.car_id,
                user_id: context.instance.user_id
              }
            }, function(err, cb) {
              if (!cb.length) {
                // If it does not find anything, go next, accept post
                next();
              } else {

                // Otherwise update record
                Votes.updateAll({
                  where: {
                    car_id: context.instance.car_id,
                    user_id: context.instance.user_id
                  }
                }, context.instance, function(err, cb) {
                  console.log('cb', cb);
                });

              }
            });

          }

        }
    }

  });

};

这两种尝试的问题是,似乎没有为 Upsert 或 Udpate 执行代码。

它被命名为操作钩子而不是远程钩子。

顺便说一句,您的第一次尝试应该像这样:

module.exports = function (Votes) {
  Votes.observe('before save', function setAutoData(context, next) {
    if (context.instance) {
      if (context.isNewInstance) {
        if (context.options.accessToken) {
          context.instance.user_id = context.options.accessToken.userId;          
        }
        return next();
      }else {
    Votes.count({
      where: {
        car_id: context.instance.car_id,
        user_id: context.instance.user_id,
        vote_value: context.instance.vote_value
      }
    }, function(err, count){
         if(err) return next(err);
             if(count > 0) next(SuitableError);
             next();
           });
      }
    }    
  });
};

您只需修改用户id,即可完成操作。无需额外 update/upsert.

并且如果这不是新实例,则检查具有相同标准的先前投票,如果存在则拒绝它,否则允许它。

也有一个简单的解决方法,不用hooks

Votes.vote = function(data, options, cb){
  var userId = options && options.accessToken && options.accessToken.userId;
  if(!userId){
    return cb(UserNotFound); //return error
  }
  Votes.upsertWithWhere({
    car_id: data.car_id,
    user_id: userId
  }, {
       car_id: data.car_id,
       user_id: userId,
       vote_value: data.vote_value
  }, function(err, result){
    if(err) return cb(err);
    cb(null, result);
  });
};

Votes.remoteMethod('vote', {
    accepts: [
      {
        arg: 'data',
        type: 'Object',
        required: true,
        http: {source: 'body'}
      },
      {
        arg: 'options',
        type: 'Object',
        http: "optionsFromRequest"
      }
    ],
    returns: {root: true, type: 'object'},
    http: {verb: 'post', status: 201, path: '/vote'}
  });