63

Nodejs プロジェクトで Sequelize を使用していますが、解決に苦労している問題を見つけました。基本的に、オブジェクトとしてデータベースに挿入するよりも、サーバーからオブジェクトの配列を取得する cron があります (この場合は cartoons )。しかし、オブジェクトの 1 つを既に持っている場合は、それを更新する必要があります。

基本的に、オブジェクトの配列があり、BulkCreate() メソッドを使用できます。しかし、Cron が再起動しても解決しないため、upsert true フラグを使用して何らかの更新が必要でした。そして主な問題: これらすべての作成または更新の後に一度だけ起動するコールバックが必要です。どうすればそれができるか考えている人はいますか?オブジェクトの配列を反復処理します..それを作成または更新してから、単一のコールバックを取得しますか?

注目してくれてありがとう

4

9 に答える 9

94

docsからwhere、オブジェクトを取得したら、更新を実行するためにクエリを実行する必要はありません。また、promise を使用すると、コールバックが簡素化されます。

実装

function upsert(values, condition) {
    return Model
        .findOne({ where: condition })
        .then(function(obj) {
            // update
            if(obj)
                return obj.update(values);
            // insert
            return Model.create(values);
        })
}

使用法

upsert({ first_name: 'Taku' }, { id: 1234 }).then(function(result){
    res.status(200).send({success: true});
});

ノート

  1. この操作はアトミックではありません。
  2. 2 つのネットワーク呼び出しを作成します。

つまり、アプローチを再考し、おそらく 1 つのネットワーク呼び出しで値を更新するだけで、次のいずれかを実行することをお勧めします。

  1. 返された値 (つまり、rows_affected) を見て、何をすべきかを決定します。
  2. 更新操作が成功した場合、成功を返します。これは、リソースが存在するかどうかは、このサービスの責任範囲外であるためです。
于 2016-12-20T17:38:45.957 に答える
27

アップサートを使用することができます 。それはずっと簡単です。

実装の詳細:

  • MySQL - 単一のクエリとして実装INSERT values ON DUPLICATE KEY UPDATE values
  • PostgreSQL - 例外処理を伴う一時的な関数として実装:INSERT EXCEPTION WHEN unique_constraint UPDATE
  • SQLite - 2 つのクエリとして実装されINSERT; UPDATEます。これは、行がすでに存在するかどうかに関係なく、更新が実行されることを意味します。
  • MSSQL -行が作成または更新されたかどうかに関係なく、SQLite は作成済みに対して未定義を返すことにMERGE and WHEN (NOT) MATCHED THEN 注意してください。これは、SQLite が常にINSERT OR IGNORE + UPDATE単一のクエリで実行されるため、行が挿入されたかどうかを知る方法がないためです。
于 2016-08-26T17:25:01.903 に答える
12

これは古い質問かもしれませんが、これは私がやったことです:

var updateOrCreate = function (model, where, newItem, onCreate, onUpdate, onError) {
    // First try to find the record
    model.findOne({where: where}).then(function (foundItem) {
        if (!foundItem) {
            // Item not found, create a new one
            model.create(newItem)
                .then(onCreate)
                .catch(onError);
        } else {
            // Found an item, update it
            model.update(newItem, {where: where})
                .then(onUpdate)
                .catch(onError);
            ;
        }
    }).catch(onError);
}
updateOrCreate(
    models.NewsItem, {title: 'sometitle1'}, {title: 'sometitle'},
    function () {
        console.log('created');
    },
    function () {
        console.log('updated');
    },
    console.log);
于 2016-01-02T05:31:06.553 に答える
0

deviceID -> pushToken マッピングを更新または作成する簡単な例を次に示します。

var Promise = require('promise');
var PushToken = require("../models").PushToken;

var createOrUpdatePushToken = function (deviceID, pushToken) {
  return new Promise(function (fulfill, reject) {
    PushToken
      .findOrCreate({
        where: {
          deviceID: deviceID
        }, defaults: {
          pushToken: pushToken
        }
      })
      .spread(function (foundOrCreatedPushToken, created) {
        if (created) {
          fulfill(foundOrCreatedPushToken);
        } else {
          foundOrCreatedPushToken
            .update({
              pushToken: pushToken
            })
            .then(function (updatedPushToken) {
              fulfill(updatedPushToken);
            })
            .catch(function (err) {
              reject(err);
            });
        }
      });
  });
};
于 2016-10-01T18:38:12.527 に答える