#rethinkdb
#rethinkdb
Вопрос:
Допустим, у меня есть два объекта, хранящихся в rethinkdb, которые я хочу сравнить, давайте назовем их old_val
and new_val
. В качестве примера предположим, что эти значения представляют задачу TODO, у которой сменился владелец и статус:
{
old_val: {
status: 'active',
content: 'buy apples',
owner: 'jordan'
},
new_val: {
status: 'done',
content: 'buy apples',
owner: 'matt'
}
}
Когда я сравниваю old_val
и new_val
, я хотел бы получить новый объект, new_val
содержащий только поля, которые отличаются от old_val
. Я хочу сделать это, чтобы сэкономить байты на проводе; и упростить рендеринг изменений на моем клиенте. Результат запроса должен выглядеть примерно так:
{
old_val: {
content: 'buy apples',
owner: 'jordan',
status: 'active'
},
new_val: {
owner: 'matt',
status: 'done'
}
}
Как мне это сделать?
Ответ №1:
Решение этой проблемы состоит из трех отдельных частей:
- Создайте список полей для сравнения
- Сравните между общими полями, включите только поля, которые отличаются
- Создайте новый объект
(1) Список полей может быть сгенерирован с помощью keys()
метода. Мы можем отфильтровать эти поля, чтобы (2) включали только те, которые существуют в обоих old_val
и new_val
и чьи значения отличаются. Затем мы можем передать эту последовательность для concatMap()
построения массива пар ключ / значение, например [key0, value0, key1, value1]
. Наконец, из этой последовательности можно создать новый объект (3), применив его в качестве аргументов (используя r.args()
) к r.object()
функции.
Это происходит следующим образом:
r.expr({
old_val: {
status: 'active',
content: 'buy apples',
owner: 'jordan'
},
new_val: {
status: 'done',
content: 'buy apples',
owner: 'matt'
}
}).do((diff_raw) =>
r.expr({
old_val: diff_raw('old_val'),
// build an object only containing changes between old_val and new_val:
new_val: r.object(r.args(
diff_raw('new_val')
.keys()
// only include keys existing in old and new that have changed:
.filter((k) =>
r.and(
diff_raw('old_val').hasFields(k),
diff_raw('new_val')(k).ne(diff_raw('old_val')(k))
)
)
// build a sequence of [ k0, v0, k1, v1, ... ]:
.concatMap((k) => [k, diff_raw('new_val')(k)])
))
})
)
Это вернет:
{
"new_val": {
"owner": "matt" ,
"status": "done"
} ,
"old_val": {
"content": "buy apples" ,
"owner": "jordan" ,
"status": "active"
}
}