如何使用 mongoengine 更新嵌入式列表中的特定对象?

How can I update specific object in embedded list using mongoengine?

This is my schema model

class Address(Document):
       street = StringField()
       city = StringField()
       country = StringField()

    class Users(Document):
       user_name = StringField()
       address = ListField(EmbeddedDocumentField('Address'))

This is what my object look like:

{
  user_name: "John",
  address: [
    {
      "street": "broadway",
      "city": "new york",
      "country": "US"
    },
    {
      "street": "weymounth",
      "city": "london",
      "country": "England"
    }
  ]
}

This is my code to update the second item/object in address list:

new_address = Address(street="bourke", city="melbourne", country="Australia")

User.objects(id="1", address__country="England").update_one(set__address__S=new_address)

But this update change the first object in embedded list instead of the second one:

{
  user_name: "John",
  address: [
    {
      "street": "bourke",
      "city": "melbourne",
      "country": "Australia"
    },
    {
      "street": "weymounth",
      "city": "london",
      "country": "England"
    }
  ]
}

尝试使用 EmbeddedDocumentListField

from mongoengine import Document, StringField, EmbeddedDocumentListField, EmbeddedDocument
class Address(EmbeddedDocument):
    street = StringField()
    city = StringField()
    country = StringField()

class Users(Document):
    user_name = StringField()
    address = EmbeddedDocumentListField(Address)


addresses = []

addresses.append(Address(street="broadway", city="new york", country="US"))
addresses.append(Address(street="bourke", city="melbourne", country="Australia"))

u = Users(user_name="john", address=addresses)
u.save()

Users.objects(address__country="US").update_one(
    set__address__S=Address(street="some street", city="Paris", country="France")
    )

最终文件:

{ 
    "_id" : ObjectId("59ec3c5219185b2fb4d428fa"), 
    "user_name" : "john", 
    "address" : [
        {
            "street" : "some street", 
            "city" : "Paris", 
            "country" : "France"
        }, 
        {
            "street" : "bourke", 
            "city" : "melbourne", 
            "country" : "Australia"
        }
    ]
}

这项工作非常完美,但如果您只需要更新列表中的一个变量,您可以使用标签来完成:

set__address__S__street = "some street"

试试这个方法

u = Users.objects(user_name="john").first()
u.adress.filter(country="US").update(street="some street", city="Paris", country="France")
u.save()

推荐: 嵌入列表的每个元素都应该有一个 ObjectId (id)