Reputation: 3624
Basically I have Post Document and Comment
EmbeddedDocument
as follow:
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
request may update any combination of value1, value2 and value3 for a given comment of a given post. I use queryset update
method to do that as follow:
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,
)
But this clearly not Read–modify–write atomic operation. So hot Read–modify–write as one atomic operation?
Upvotes: 0
Views: 784
Reputation: 1253
The positional operator allows you to update list items without knowing the index position, therefore making the update a single atomic operation.
The positional operator (set__comments__S__value1) allows you to update exact comment, that will be selected by comments__id=comment_id
. That means you no need cycle to get the comment. You can do everything with one operation.
Documents may be updated atomically by using the
update_one()
,update()
andmodify()
methods on aQuerySet
ormodify()
andsave()
(with save_condition argument) on aDocument
.
Detailed here
Code to update only one Comment
with given id:
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)
Upvotes: 1