Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Query Embedded Document List in MongoEngine

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?

like image 792
Joey Hu Avatar asked Apr 12 '16 06:04

Joey Hu


1 Answers

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.

like image 108
Blakes Seven Avatar answered Sep 19 '22 04:09

Blakes Seven