Query Embedded Document List in MongoEngine

12,480

Actually you were doing it "incorrectly" in the shell as well. The format you were using requires an exact match that would "rarely" actually match conditions. It certainly would not should the inner keys of the array be stored in a different order, or most importantly that the array itself actually stored more than one element.

The correct form for the "shell" would be:

db.sku.find({ "variants": { "$elemMatch": { "name": "xxx", "value": "xxx" } } })

By the same token, the "correct" form for MongoEngine is:

Sku.objects(variants__match={ "name": "xxx", "value": "xxx" })

The __match construct here is the same thing as, and actually issues an $elemMatch statement in query to the underlying MongoDB database as a query.

Note that for a "single" element condition the general "double underscore" syntax is just fine:

Sku.objects(variants__name="xxx")

But for "multiple" conditions and/or elements within the array/list, you need $elemMatch as a MongoDB query and therefore __match.

Share:
12,480
Joey Hu
Author by

Joey Hu

A graduate student looking for a job in the SF bay area.

Updated on June 11, 2022

Comments

  • Joey Hu
    Joey Hu almost 2 years

    I need query a list with all embedded documents in mongoengine. Here is my schema:

    class Variant(EmbeddedDocument):
        name = StringField(required=True)
        value = StringField(required=True)
    
    class Sku(Document):
        variants = ListField(EmbeddedDocumentField(Variant))
    

    I can do it using mongo shell with:

    db.sku.find({variants: [{'name': 'xxx', 'value': 'xxx'}]}).pretty()
    

    But I haven't figure out a way to do it in mongoengine. I need the list in the document is exactly the same with the list I put in the query. Any ideas?

  • Joey Hu
    Joey Hu about 8 years
    What if I need two elements in the array? Like: db.sku.find({variants: [{'name': 'xxx', 'value': 'xxx'},{'name': 'yyy', 'value': 'yyy'} ]}).pretty()
  • Blakes Seven
    Blakes Seven about 8 years
    @JoeyHu That is a different question to what you asked, and this answers only the question you "actually asked". If you have a new question then Ask a new Question instead. That's how we do it here, as one question and one definitive answer. This question you asked is answered.
  • Javad Asoodeh
    Javad Asoodeh almost 4 years