2015-03-31 3 views
0

Скажем, у меня есть следующая структура данных:Rethinkdb атомное получать и обновлять

{ "name": "i1", "time": 1, "status": 1} 
{ "name": "i2", "time": 2, "status": 1} 
{ "name": "i3", "time": 3, "status": 1} 
{ "name": "i4", "time": 4, "status": 2} 

Мне нужно, чтобы получить элемент с наибольшим временем и «статус» = 1. Тогда обновлять это «состояние» до 2, все это атомарно, поэтому один и тот же элемент не может быть получен другим потребителем в одно и то же время.

Возможно ли это с rethinkdb?

ответ

1

Поскольку атомарность в RethinkDB гарантируется только на уровне документа, это лишь частично возможно.

Вы можете сделать что-то вроде этого:

r.table(...) 
    .orderBy(index=r.desc("time")) 
    .filter({status: 1}) 
    .limit(1) 
    .update(r.branch(r.row["status"] == 1, {status: 2}, {}), return_changes=True) 

Все внутри из update будет применяться атомарно. Поэтому, если статус записи уже был установлен на 2 другим клиентом, запрос вернет {unchanged: 1}, и вы сможете запустить его снова, пока он не будет успешно выполнять обновление.

Однако это не гарантирует, что в момент выполнения обновления выбранный документ по-прежнему остается самым большим. Другой клиент мог вставить новый документ с большим временем, пока этот запрос выполнялся, что сделало бы запрос обновить статус только второго по величине документа до 2.

Для полной защиты от этого вам необходимо будет используйте явный мьютекс или блокировку чтения/записи для таблицы.

+0

Спасибо! Поиск «без изменений» делает трюк. В моем случае, выбрав по самому большому «времени», подхода «наилучшего усилия» достаточно. Однако, по крайней мере, в python выполнение обновления по лимиту (1) приведет к повышению «TypeError:« r.row »не является вызываемым, используйте« r.row [...] »вместо этого». – sanyi

+0

Ах, извините, мой запрос использовал синтаксис JavaScript. Я собираюсь отредактировать его. –

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