Как принудительно применить и применить не более (или точно) одного объекта с истинным флагом в разделе CosmosDB?

#azure #nosql #azure-cosmosdb

Вопрос:

У меня есть небольшая коллекция документов в разделе. Я хотел бы отметить точно одну из этих сущностей как включенную в разделе. Быть включенным означает, что в документе установлен isEnabled флаг true. Когда документ обновляется или вставляется со isEnabled значением true, в этой транзакции должны быть все остальные документы isEnabled:false . Если документ удаляется или изменяется с isEnabled true на false, то последний измененный документ должен стать включенным, если осталась какая-либо запись. Раздел никогда не должен переходить в несогласованное состояние. Должно быть возможно иметь только один включенный документ, если только нет нулевых документов

Существует ли схема реализации такого рода государства? Я попробовал несколько подходов, но во всех них, похоже, есть какие-то дыры.

Комментарии:

1. I've attempted a few approaches but they all seem to have some holes in them — Пожалуйста, отредактируйте свой вопрос и укажите подходы, которые вы пытались использовать, и проблемы, с которыми вы столкнулись с ними.

2. Помогли ли предоставленные ответы решить вашу проблему? Если да, пожалуйста, подумайте о принятии одного из них.

Ответ №1:

Используйте уникальные ключи. И назови это disabledAt вместо isEnabled этого .

Когда вам нужно переключить активный документ, вы можете открыть транзакцию.

  1. Начать транзакцию
  2. В старом документе установите disabledAt текущую дату и время UTC или галочки
  3. В новом документе установите disabledAt значение null или удалите его
  4. Зафиксировать транзакцию

Вы можете выполнять транзакции с помощью SDK или с помощью пользовательских функций. Вероятно, вы также можете использовать пост-триггеры, поскольку они выполняются в рамках одной транзакции.

Это гарантирует, что у вас есть только один документ без значения для disabledAt . Это работает, потому что вы можете выполнять транзакции с гарантированной согласованностью, пока вы находитесь в пределах одного раздела.

Ответ №2:

Моя мысль состояла бы в том, чтобы переместить это состояние в выделенный элемент, а не распределять его между элементами. Этот отдельный элемент метаданных для каждого раздела будет иметь свойство типа activeItemId и будет иметь значение либо id активного документа, либо null, если он не активен.

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