Ich verwende Sequelize in meinem Nodejs-Projekt und habe ein Problem gefunden, das ich schwer zu lösen habe .. Im Grunde habe ich einen Cron, der ein Array von Objekten von einem Server erhält, als es in meiner Datenbank als Objekt (für diesen Fall Cartoons). Wenn ich aber bereits eines der Objekte habe, muss ich es aktualisieren.
Grundsätzlich habe ich ein Array von Objekten und könnte die BulkCreate () -Methode verwenden. Aber als der Cron neu startet, löst er das Problem nicht. Daher musste ich ein Update mit einem Up-True-Flag durchführen. Und das Hauptproblem: Ich muss einen Rückruf haben, der nur einmal ausgelöst wird, nachdem alle diese erstellt oder aktualisiert wurden. Hat jemand eine Idee, wie ich das machen kann? Durch ein Array von Objekten iterieren ... erstellen oder aktualisieren und danach einen einzelnen Rückruf erhalten?
Danke für ihre Aufmerksamkeit
Von docs müssen Sie nicht where
abfragen, um die Aktualisierung durchzuführen, sobald Sie das Objekt haben. Die Verwendung von Versprechen sollte auch Rückrufe vereinfachen:
Implementierung
function upsert(values, condition) {
return Model
.findOne({ where: condition })
.then(function(obj) {
if(obj) { // update
return obj.update(values);
}
else { // insert
return Model.create(values);
}
}
})
}
Verwendungszweck
upsert({ first_name: 'Taku' }, { id: 1234 }).then(function(result){
res.status(200).send({success: true});
});
Hinweis
das heißt, es ist ratsam, den Ansatz zu überdenken und wahrscheinlich nur die Werte in einem Netzwerkaufruf zu aktualisieren. Entweder:
Die Idee von Ataik hat mir gefallen, aber etwas kürzer:
function updateOrCreate (model, where, newItem) {
// First try to find the record
return model
.findOne({where: where})
.then(function (foundItem) {
if (!foundItem) {
// Item not found, create a new one
return model
.create(newItem)
.then(function (item) { return {item: item, created: true}; })
}
// Found an item, update it
return model
.update(newItem, {where: where})
.then(function (item) { return {item: item, created: false} }) ;
}
}
Verwendungszweck:
updateOrCreate(models.NewsItem, {slug: 'sometitle1'}, {title: 'Hello World'})
.then(function(result) {
result.item; // the model
result.created; // bool, if a new item was created.
});
Optional: Fügen Sie hier die Fehlerbehandlung hinzu. Es wird jedoch dringend empfohlen, alle Versprechen einer Anforderung zu verketten und am Ende einen Fehlerbehandler zu verwenden.
updateOrCreate(models.NewsItem, {slug: 'sometitle1'}, {title: 'Hello World'})
.then(..)
.catch(function(err){});
Sie können upsert .__ verwenden. Es ist viel einfacher.
Implementierungsdetails:
MySQL - Wird als einzelne Abfrage implementiert. INSERT-Werte ON DUPLICATE KEY
UPDATE-Werte PostgreSQL - Implementiert als temporäre Funktion mit Ausnahmebehandlung: INSERT EXCEPTION WHEN unique_constraint UPDATE
SQLite - Implementiert als zwei Abfragen INSERT; AKTUALISIEREN. Das bedeutet, dass Die Aktualisierung wird unabhängig davon ausgeführt, ob die Zeile bereits vorhanden war oder nicht
Dies könnte eine alte Frage sein, aber ich habe es getan:
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);
Sie möchten, dass Sie Ihre Sequelize-Anrufe in einem async.each einschließen.
Dies kann mit dem benutzerdefinierten Ereignisemitter erfolgen.
Angenommen, Ihre Daten befinden sich in einer Variablen namens Daten.
new Sequelize.Utils.CustomEventEmitter(function(emitter) {
if(data.id){
Model.update(data, {id: data.id })
.success(function(){
emitter.emit('success', data.id );
}).error(function(error){
emitter.emit('error', error );
});
} else {
Model.build(data).save().success(function(d){
emitter.emit('success', d.id );
}).error(function(error){
emitter.emit('error', error );
});
}
}).success(function(data_id){
// Your callback stuff here
}).error(function(error){
// error stuff here
}).run(); // kick off the queries
Hier ein einfaches Beispiel, das entweder die deviceID -> pushToken-Zuordnung aktualisiert oder erstellt:
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);
});
}
});
});
};
sie können in sequelize die Methoden findOrCreate
und dann update
verwenden. Hier ist ein Beispiel mit async.js
async.auto({
getInstance : function(cb) {
Model.findOrCreate({
attribute : value,
...
}).complete(function(err, result) {
if (err) {
cb(null, false);
} else {
cb(null, result);
}
});
},
updateInstance : ['getInstance', function(cb, result) {
if (!result || !result.getInstance) {
cb(null, false);
} else {
result.getInstance.updateAttributes({
attribute : value,
...
}, ['attribute', ...]).complete(function(err, result) {
if (err) {
cb(null, false);
} else {
cb(null, result);
}
});
}
}]
}, function(err, allResults) {
if (err || !allResults || !allResults.updateInstance) {
// job not done
} else {
// job done
});
});
User.upsert({ a: 'a', b: 'b', username: 'john' })
Es wird versucht, einen Datensatz nach Hash in 1. Parameter zu finden, um ihn zu aktualisieren. Wird er nicht gefunden, wird ein neuer Datensatz erstellt
Hier ist ein Beispiel für die Verwendung in Folgetests
it('works with upsert on id', function() {
return this.User.upsert({ id: 42, username: 'john' }).then(created => {
if (dialect === 'sqlite') {
expect(created).to.be.undefined;
} else {
expect(created).to.be.ok;
}
this.clock.tick(1000);
return this.User.upsert({ id: 42, username: 'doe' });
}).then(created => {
if (dialect === 'sqlite') {
expect(created).to.be.undefined;
} else {
expect(created).not.to.be.ok;
}
return this.User.findByPk(42);
}).then(user => {
expect(user.createdAt).to.be.ok;
expect(user.username).to.equal('doe');
expect(user.updatedAt).to.be.afterTime(user.createdAt);
});
});