Подтвердить что ты не робот

Sequelize upsert

Мне нужно получить идентификатор для вставленной/обновленной записи при использовании .upsert() в sequelize.

прямо сейчас .upsert() возвращает логическое значение, указывающее, была ли создана или обновлена ​​строка.

return db.VenueAddress.upsert({
            addressId:address.addressId,
            venueId: venue.venueId,
            street: address.street,
            zipCode: address.zipCode,
            venueAddressDeletedAt: null
        }).then(function(test){
            //test returned here as true or false how can i get the inserted id here so i can insert data in other tables using this new id?
        });
4b9b3361

Ответ 1

Я не думаю, что возвращение записанной записи было доступно, когда ОП задал этот вопрос, но с тех пор это было реализовано с помощью этого PR. Начиная с Sequelize v4.32.1, вы можете передать логическое значение, returning в качестве параметра запроса, для выбора между возвратом массива с записью и логическим значением, или просто логическое значение, указывающее, была ли создана новая запись.

Вам все еще нужно указать идентификатор записи, которую вы хотите удалить, или будет создана новая запись.

Например:

const [record, created] = await Model.upsert(
  { id: 1, name: 'foo' }, // Record to upsert
  { returning: true }     // Return upserted record
);

Ответ 2

Я хотел, чтобы upsert возвращал созданный или обновленный объект. Это происходит не потому, что, по-видимому, поддерживается только PGSQL.

Итак, я создал наивную реализацию, которая, вероятно, будет неэффективной и, возможно, со всеми видами условий гонки, сделает следующее:

Sequelize.Model.prototype.findCreateUpdate = function(findWhereMap, newValuesMap) {
  return this.findOrCreate({
    where: findWhereMap, 
    defaults: findWhereMap
  })
  .spread(function(newObj, created) {
    // set:
    for(var key in newValuesMap) {
      newObj[key] = newValuesMap[key];
    }

    return newObj.save();
  });
};

Использование при попытке создать/обновить ход в игре (надуманный пример alert!):

models.Game
.findOne({where: {gameId: gameId}})
.then(function(game) {
  return db.Move.findCreateUpdate(
    {gameId: gameId, moveNum: game.moveNum+1}, 
    {startPos: 'kr4', endPos: 'Kp2'}
  );
});

Ответ 3

Это то, что сработало для меня:

Model.upsert({
    title:your title,
    desc:your description,
    location:your locations
}).then(function (test) {
    if(test){
        res.status(200);
        res.send("Successfully stored");
    }else{
        res.status(200);
        res.send("Successfully inserted");
    }
})

Он проверит db, чтобы найти на основе вашего первичного ключа. Если он найдет то, он обновит данные, иначе он создаст новую строку/вставку в новую строку.

Ответ 4

Я знаю, что это старый пост, но в случае, если это поможет кому-либо

const upsert = async (model: any, values: any, condition: any): Promise<any> => {
  const obj = await model.findOne({ where: condition })
  if (obj) {
    // only do update is value is different from queried object from db
    for (var key in values) {
      const val = values[key]
      if (parseFloat(obj[key]) !== val) {
        obj.isUpdatedRecord = true
        return obj.update(values)
      }
    }
    obj.isUpdatedRecord = false
    return obj

  } else {
    // insert
    const merged = { ...values, ...condition }
    return model.create(merged)
  }
}

Ответ 5

janmeier сказал:

Это поддерживается только postgres, поэтому для обеспечения соответствия API по диалектам это невозможно.

см. ниже: https://github.com/sequelize/sequelize/issues/3354

Ответ 6

Я сам решил следующее:

return db.VenueAddress.upsert({
        addressId:address.addressId,
        venueId: venue.venueId,
        street: address.street,
        zipCode: address.zipCode,
        venueAddressDeletedAt: null
    },{individualHooks: true}).then(function(test){ 
        // note individualHooks
    });