2016-11-01 5 views
1

После изучения некоторых вопросов и вопросов о RithinkDB github мне не удалось прийти к четкому выводу, возможно ли атомное Upsert?Правильный Upsert (поле Atomic Update Counter или Insert Document) с RethinkDB

По существу, я хотел бы выполнить ту же операцию, что и ZINCRBY, используя Redis.

Если член не существует в отсортированном наборе, он добавляется с шагом как его счет (как если его предыдущая оценка была 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 @AtnNm. Спасибо за ваш ответ, но я не полностью следую вашему примеру. Мне нечего заменить, поэтому get вернет нуль или ошибку. Я хочу вставить строку с именем {name: "A", score: 1, type: player}. Если A уже находится в таблице, я хочу принять оценку и обновить ее. Я хочу вставить документ или в случае, если документ существует, чтобы увеличить счет. Если я следую вашему примеру, эта функция требует, чтобы игрок уже существовал, и создает запись оценки или увеличивается, если она уже существует. – Astronaut

+0

Вариант использования аналогичен Redis zincrby или PouchDB https://github.com/pouchdb/upsert – Astronaut

+1

Случай, когда игрок не существует, обрабатывается 'r.branch' на' row.eq (null) ' , Я отредактировал ответ с примером и ссылкой на документацию. – 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)}); 
    } 
    } 
) 

Считаете ли вы, что это более читаемый/элегантный или вы видите какие-либо проблемы с кодом по сравнению с вашим образцом?

 Смежные вопросы

  • Нет связанных вопросов^_^