ilikecats
ilikecats

Reputation: 319

Changing a value in a listfield of embedded documents on MongoEngine

I am learning how to use MongoEngine and MongoDB, and I know how to query over Listfield(EmbeddedDocumentField) from this question:

can't query over ListField(EmbeddedDocumentField)

Sort of nasty. Kind of wish there was something easier than that.

I know how to change the name of an agent using the same example from the link:

Agent.objects(name="Brenna Li").update_one(set__name="Brenna Smith")

But how can I change a value inside an embedded document in a listfield? For example, what is the code I need to change Brenna Li's skill level in C++ from a 6 to a 8 and her skill level in Java from 4 to a 5?

Upvotes: 0

Views: 1319

Answers (1)

Ross
Ross

Reputation: 18101

You can use the positional operator $ or S in mongoengine (so it can be used as a keyword argument). However, you can only update a single match at a time. Making it impossible to update both the Java and C++ levels in a single query - without replacing the whole Skills list (which wouldnt be very safe).

To do it in two queries you could do something like:

    class Skill(EmbeddedDocument):
       name =  StringField(required = True)
       level = IntField(required = True)

    class Agent(Document):
       name = StringField(required = True)
       email = EmailField(required = True, unique = True)
       skills = ListField(EmbeddedDocumentField(Skill))

    Agent.drop_collection()

    Agent(name="Brenna Li", email="[email protected]",
          skills=[Skill(name="Java", level=2),
                  Skill(name="Surfing", level=6),
                  Skill(name="c++", level=4)]).save()

    Agent.objects.filter(name="Brenna Li", skills__name="Java").update(set__name="Brenna Smith", inc__skills__S__level=1)
    Agent.objects.filter(name="Brenna Smith", skills__name="c++").update(inc__skills__S__level=1)

Upvotes: 2

Related Questions