Как сделать атомарное чтение-изменение-запись в mongoengine? - PullRequest
0 голосов
/ 10 октября 2019

В основном у меня есть почтовый документ и Comment EmbeddedDocument следующим образом:

class Comment(EmbeddedDocument):
    value1 = StringField(max_length=200,)
    value2 = StringField(max_length=200,)
    value3 = StringField(max_length=200,)
    id = UUIDField(required=True, primary_key=True)

class Post(Document,):
    comments = EmbeddedDocumentListField(Comment, required=False) 

PUT запрос может обновить любую комбинацию значений1, значений2 и значений3 для данного комментария к данному сообщению. Я использую метод queryset update, чтобы сделать это следующим образом:

post = Post.objects.get(id=post_id)
comment = None
for comm in post.comments:
    if comm.id == comment_id:
        comment = comm

Post.objects(
    id=post_id, 
    comments__id=comment_id
).update(
        set__comments__S__value1=new_value1 or comment.value1,
        set__comments__S__value2=new_value2 or comment.value2,
        set__comments__S__value3=new_value3 or comment.value3,
)

Но это явно не Чтение-изменение-запись атомарная операция. Настолько горячее чтение-изменение-запись как одна атомарная операция?

1 Ответ

1 голос
/ 19 октября 2019

Позиционный оператор позволяет обновлять элементы списка, не зная позиции индекса, поэтому делает обновление одной атомарной операцией.

Позиционный оператор (set__comments__S__value1) позволяет точно обновлятькомментарий, который будет выбран comments__id=comment_id. Это означает, что вам не нужен цикл, чтобы получить комментарий. Вы можете сделать все с помощью одной операции.

Документы можно обновлять атомарно, используя методы update_one(), update() и modify() в QuerySet или modify() и save()(с аргументом save_condition) на Document.

Подробно здесь

Код для обновления только одного Comment с указанным идентификатором:

def put(value1=None, value2=None, value3=None):
   data = {}
   if value1:
       data['set__comments__S__value1'] = value1
   if value2:
       data['set__comments__S__value2'] = value2
   if value3:
       data['set__comments__S__value3'] = value2
   Post.objects(
       id='5dab09cade20c4423a9cb4d1', 
       comments__id='18f75928-36d5-415d-b8a9-18488f954e68'
   ).update(**data)
...