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?
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
.