2016-11-01 95 views
1

在RethinkDB github上看到一些SO問題和問題後,我沒有得出一個明確的結論,如果原子Upsert是可能的?正確的Upsert(原子更新計數器字段或插入文檔)與RethinkDB

本質上我想使用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

Hi @AnnNm。感謝您的回覆,但我沒有完全遵循您的示例。 我沒有任何東西可以替換,因此get會返回null或錯誤。我想插入一行{name:「A」,得分:1,類型:player}。如果A已經在桌上,那麼我想要拿分並更新它。 我想插入文檔或萬一文檔存在增加分數。如果我按照您的示例,該功能要求玩家已經存在,並創建分數記錄或增量(如果已經存在)。 – Astronaut

+0

用例類似於Redis zincrby或PouchDB https://github.com/pouchdb/upsert – Astronaut

+1

玩家不存在的情況由'row.eq(null)'上的'r.branch'處理' 。我用一個例子和文檔的鏈接編輯了答案。 – AtnNn

0

所以我最終使用下面的代碼繞過no更新問題。

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)}); 
    } 
    } 
) 

你認爲這是更可讀/優雅或你看到比你的樣品與代碼的任何問題?