4

rethinkDB の insert()に upsert オプションがあることは知っています。たとえば、ドキュメントから:

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

しかし、間違った、または古いスーパーパワーを持つ の既存のレコードが存在する可能性があり、既存のレコードを挿入または更新{superhero: 'Iron Man'}したいとしますか?{ superhero: 'Iron Man', superpower: 'Arc Reactor' }{superhero: 'Iron Man'}

要するに、特定のフィールドが一致した場合にのみ既存のレコードが更新されるようにするには、どうすればアップサートできますか?

編集:これは .replace() で行われるようです:

replace() ドキュメントの重要な部分は次のとおりです

テーブルにないキーでポイント置換を行うと、新しいドキュメントを挿入できます

「ポイント置換」が何を意味するのかはわかりませんが、単に置換を意味すると思います。

var latestDoc = { superhero: 'Iron Man', superpower: 'Arc Reactor' }
var mergeOrCreate = function(existingDoc) {
  if ( existingDoc ) {
    return existingDoc.merge(latestDoc)
  } else {
    return latestDoc
  }
}
rethinkdb.table('marvel')
  .filter({ superhero: 'Iron Man'})
  .replace(mergeOrCreate),
).run(conn, callback)

ただし、テストでは、「mergeOrCreate」関数には、実際のドキュメントやカーソルではなく、別の関数が引数として与えられています。

4

1 に答える 1

5

最初のコード ブロックは、最初の質問に対する答えです。superheroただし、それがテーブルの主キーであると想定しています。

テーブルを作成するときに、テーブルの主キーを設定できます。

r.tableCreate('marvel', {primaryKey: 'superhero'}).run(conn, cb)

2 番目のコード ブロックには 2 つの間違いがあります。

ifまず、ステートメントはクライアント側で評価されるため、mergeOrCreate 関数は機能しません。ステートメントr.branchに相当するものを作成するには、次を使用する必要があります。if

var mergeOrCreate = function(existingDoc) {
  return r.branch(existingDoc,    /* if */
    existingDoc.merge(latestDoc), /* then */
    latestDoc)                    /* else */
}

次に、getは と同じ構文をサポートしていませんfilter。その引数は主キーの値でなければなりません。主キーがsuperheroの場合:

r.table('marvel')
  .get('Iron Man')

最後に、superheroが主キーでない場合は、別の種類のクエリを作成する必要があります。同じsuperhero. これを書く1つの方法は次のとおりです。

r.table('marvel')
  .insert(
   r.table('marvel')
     .filter({ superhero: 'Iron Man' })
     .coerceTo('array')
     .do(function(docs){
        return r.branch(
          docs,
          docs.merge(latestDoc),
          latestDoc)
        }),
   { upsert: true })
  .run(conn, cb);

このクエリは複数のドキュメントに依存するため、アトミックではないことに注意してください。

于 2013-12-11T17:26:00.273 に答える