2016-11-01 4 views
1

RethinkDB githubに関するいくつかの質問と問題を見て、アトミックUpsertが可能なら明確な結論に達しませんでしたか?RethinkDBを使った適切なUpsert(Atomic Update Counter FieldまたはInsert Document)

私は、Redisを使用してZINCRBYと同じ操作を基本的に実行したいと思います。

部材がソートセット内に存在しない場合(以前のスコアは0.0であったかのように)、それは、そのスコアとしてインクリメント が付加されています。キーに が存在しない場合は、指定されたメンバーを単独メンバーとして持つ新しいソートセット が作成されます。

現在の実装は、私が使用しているほぼすべてのデータベースとは異なるようです。置換または挿入されたデータは更新されません。これは、最後の訪問の更新、クリック数の更新、商品数の更新などの簡単な使用例です。私はこれを行う簡単な方法を見ることができないので、私は非常に明白な何かを逃している必要があります。

答えて

1

はい、可能です。キーのgetの後に、アトミックreplaceを実行します。このような何かがうまくいくかもしれない:

function set_or_increment_score(player, points){ 
    return r.table('scores').get(player).replace(
    row => 
     { id: player, 
     score: r.branch(
       row.eq(null), 
       points, 
       row('score').add(points)) 
     }); 
} 

それは次のように動作しています

> set_or_increment_score("alice", 1).run(conn) 
{ inserted: 1 } 
> set_or_increment_score("alice", 2).run(conn) 
{ replaced: 1 } 

ためget戻っnull文書が存在せず、非既存のドキュメントタンズのreplaceそれは動作します挿入物に入れる。 documentation for replace

+0

こんにちは@AtnNm。あなたの返信をありがとうが、私は完全にあなたの例に従っていません。 私は何も置き換えないので、getはnullまたはエラーを返します。 {name: "A"、score:1、type:player}の行を挿入します。 Aがすでにテーブルに入っている場合は、スコアを取得して更新します。 文書を挿入したい場合や、文書が存在してスコアを増やしたい場合に備えてください。あなたの例に従えば、その機能はプレーヤーが既に存在することを要求し、スコアレコードを作成するか、すでに存在する場合は増分します。 – Astronaut

+0

ユースケースはRedis zincrbyまたはPouchDB https://github.com/pouchdb/upsertに似ています – Astronaut

+1

プレーヤーが存在しない場合は、 'row.eq(null)'の 'r.branch'によって処理されます。 。私は例とドキュメントへのリンクで答えを編集しました。 – AtnNn

0

したがって、次のコードを使用して、更新プログラムの問題を回避します。

r.db("test").table("t").insert(
    {id:"A", type:"player", species:"warrior", score:0, xp:0, armor:0}, 
    {conflict: function(id, oldDoc, newDoc) { 
     return newDoc.merge(oldDoc).merge(
     {armor: oldDoc("armor").add(1)}); 
    } 
    } 
) 

これは読みやすく/エレガントであると思いますか、コードに問題があると思われますか?

関連する問題