0

It's too slow when I update a ListField with mongoengine.Here is an example

class Post(Document):
    _id = StringField()
    txt = StringField()
    comments = ListField(EmbeddedDocumentField(Comment))

class Comment(EmbeddedDocument):
    comment = StringField()
    ...

...

position = 3000
_id = 3
update_comment_str = "example"

#query
post_obj = Post.objects(_id=str(_id)).first()

#update
post_obj.comments[position].comment = update_comment_str

#save
post_obj.save()

The time it cost increases with the increase of the length of post_obj.comments. How to optimize it?

DachuanZhao
  • 1,181
  • 3
  • 15
  • 34

1 Answers1

2
Post.objects(id=str(_id)).update(**{"comments__{}__comment".format(position): update_comment_str})

In your code.

  1. You fetched the whole document into python instance which will take place in RAM.

  2. Then update 3000 th comments which will do some magic in mongoengine(marking changed fields and so on).

  3. Then saves document.

In my answer,I have sent the update instruction to mongodb instead of fetching whole documents with N comments into Python which will save memory(RAM) and time.

The mongoengine/MongoDB supports index support update like

set__comments__1000__comment="blabla"

In order to give position using variable, I've used python dictionary and kwargs trick.

Erdenezul
  • 597
  • 1
  • 7
  • 10
  • You solve my problem.Thank you.But the code should be added "set__": ```Post.objects(id=str(_id)).update(**{"set__comments__{}__comment".format(position): update_comment_str}``` – DachuanZhao May 06 '19 at 18:15
  • set will be added automatically in mongoengine. – Erdenezul May 06 '19 at 18:34