Как я могу сравнить два объекта rethinkdb, чтобы создать новый объект, содержащий только их различия?

#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. Создайте список полей для сравнения
  2. Сравните между общими полями, включите только поля, которые отличаются
  3. Создайте новый объект

(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"
  }
}