12 Stimmen

Wie man ein RethinkDB-atomisches Update erstellt, falls das Dokument existiert, ansonsten einfügt?

Wie macht man ein rethinkdb atomares Update, wenn das Dokument existiert, ansonsten einfügt?

Ich möchte etwas wie:

var tab = r.db('agflow').table('test');
r.expr([{id: 1, n: 0, x: 11}, {id: 2, n: 0, x: 12}]).forEach(function(row){
  var _id = row('id');
  return r.branch(
    tab.get(_id).eq(null),  // 1
    tab.insert(row),        // 2 
    tab.get(_id).update(function(row2){return {n: row2('n').add(row('n'))}}) // 3
  )})

Allerdings ist dies nicht vollständig atomar, da zwischen dem Zeitpunkt, an dem überprüft wird, ob das Dokument existiert (1), und dem Einfügen (2) ein anderer Thread es einfügen könnte.

Wie macht man diese Abfrage atomar?

20voto

wedesoft Punkte 2463

Ich denke, die Lösung besteht darin, den

conflict="update"

Parameter an die insert Methode zu übergeben.

Siehe auch RethinkDB-Dokumentation zu insert

3voto

Daniel Mewes Punkte 1876

Um den inneren Teil atomar zu machen, können Sie ersetzen verwenden:

tab.get(_id).replace(function(row2){
  return r.expr({id: _id, n: row2('n').add(row('n'))})
          .default(row)
})

Die Verwendung von ersetzen ist derzeit der einzige Weg, um vollständig atomare Upserts mit nicht trivialem Update-Betrieb durchzuführen.

1voto

Brigand Punkte 81205

Dies ist ein Standard-Datenbankvorgang, der als "upsert" bezeichnet wird.

Unterstützt RethinkDB Upserts?

Eine weitere Frage von Sergio Tulentsev. Die erste öffentliche Version enthielt keine Unterstützung für Upserts, aber jetzt kann dies durch Übergabe eines zusätzlichen Flags an insert erfolgen:

r.table('marvel').insert({ 
      superhero: 'Iron Man', 
      superpower: 'Arc Reactor' 
  }, {upsert: true}).run() 

Wenn auf true gesetzt, wird das neue Dokument aus insert das vorhandene überschreiben.

Quelle: <a href="http://www.rethinkdb.com/blog/answers-to-common-questions/" rel="nofollow">Antworten auf häufig gestellte Fragen zu RethinkDB</a>

0voto

Robert Zaremba Punkte 7318

OK, ich habe herausgefunden, wie es geht.

Die Lösung besteht darin, zuerst insert zu versuchen, und wenn es fehlschlägt, machen wir update:

var tab = r.db('agflow').table('test');
tab.delete();
r.expr([{id: 1, n: 0, x: 11}, {id: 2, n: 0, x: 12}]).forEach(function(row){
  var _id = row('id');
  var res = tab.insert(row);
  return r.branch(
    res('inserted').eq(1),
    res,
    tab.get(_id).update(function(row2){return {n: row2('n').add(1)}})
  )})

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X