Возвращение информации об успешном обновлении Pymon go - PullRequest
0 голосов
/ 30 марта 2020

Я пишу приложение, которое нуждается в семантике сравнения и установки в mon go.

У меня есть небольшая коллекция A (до 200 или около того в производстве) документов, которые выглядят например:

{
  _id: str,
  field: str
  last_known_version: int,
  data: binary_blob
}

И иметь путь к коду:

  • Считывает текущие данные и текущие последние известные версии (LKV) как словари field -> value из A.

  • Затем выполняет некоторые вычисления для данных, находя новую последнюю известную версию.

  • Затем он пытается обновить документы в коллекции A, где последняя известная версия не изменилась по сравнению с тем, что мы прочитали (по существу, оптимистично делает сравнение и набор), возвращая field s где обновление прошло успешно
  • Наконец, мы делаем дальнейшие расчеты на основе успешных обновлений полей.

В псевдокоде это выглядит примерно так:

def operation():
   data_by_field, lkv_by_field = read_data_and_last_known_version_by_field(A)
   new_data_by_field, new_lkv = process(data_by_field)
   successful_updates: Set[str] = compare_and_set(
                                    new_data,
                                    expected_version=lkv_by_field,
                                    new_version=new_lkv
                                  )
   conditionally_do_more_stuff(successful_updates)

Моя проблема в том, как вернуть значения из сравнения и установки. Я мог бы сделать find_one_and_update для каждого поля:

successful = {}
for field in fields:
   r = A.find_one_and_update(
            {'_id': id_from_field(field), 'last_known_version': expected_last_known_version},
            {
                '$setOnInsert': {

                    'field': field
                },
                'set': {
                    'data': data[field],
                    'last_known_version': lkv[field]
                }
            },
            projection='field',
            upsert=True
        )
        for doc in r:
            sucessful.add(doc['field'])

Но я не хочу брать на себя 200 сетевых обращений к серверу mon go или навязывать причинный порядок того, как происходят эти обновления. Поэтому вместо этого я хотел бы иметь возможность использовать bulk_write с набором предварительно рассчитанных аппетов.

upserts = []
for field in fields:
   upserts.append(
       UpdateOne(
            filter={'_id': id_from_field(field), 'last_known_version': expected_last_known_version},
            update={
                '$setOnInsert': {

                    'field': field
                },
                'set': {
                    'data': data[field],
                    'last_known_version': lkv[field]
                }
            },
            upsert=True
       )
   )
A.bulk_write(upserts, ordered=False)

Однако, насколько мне известно, не существует очевидного способа вернуть документ из UpdateOne или массового написания. Кроме того, не составит труда вычислить field s из _id любых обновленных или вставленных документов, поэтому было бы полезно вернуть _id.

Есть ли идиоматизм c способ сделать это в пн go?

...