Mongoengine: Querying EmbeddedDocumentListField with operators 'Client' object has no attribute 'name__icontains'

Created on 27 Sep 2017  路  5Comments  路  Source: MongoEngine/mongoengine

I have an EmbeddedDocumentListField with Following Fields
Clients [{"name","email","mobile",..},.....]

now i am able to filter pure on pure fld=value

but unable to use any of the operators along with the fields.
is there a way to do this using mongoengine, can someone help me

If not i would implementing something of my own

Awaiting Response

Most helpful comment

I believe @rp-21 is talking about the .filter of the EmbeddedDocumentList like in:

class Client(me.EmbeddedDocument):
    name = me.StringField()

class Doc(me.Document):
    clients = me.EmbeddedDocumentListField(Client)

d = Doc(clients=[Client(name='John')]).save()
d.clients.filter(name='John')           # Out: [<Client: Client object>]
d.clients.filter(name__icontains='J')       # raises AttributeError: 'Client' object has no attribute 'name__icontains'

That EmbeddedDocumentList.filter does not support operators like __gte, __lte, __icontains, etc, it only supports simple comparison. I understand that users can get confused with the queryset.filter that has those fancy operators. Implementing those operators here would be overkill, I see 2 options:

  • Improve the doc of the EmbeddedDocumentList.filter and mention that it does not supports fancy operator like queryset.filter
  • Get rid of EmbeddedDocumentList.filter, I believe we should do this on the long run because the benefits of this method are limited and its confusing with queryset.filter (Just my opinion :))

I'll push a PR to improve the doc shortly

All 5 comments

can you provide sample code to reproduce this error?

I believe @rp-21 is talking about the .filter of the EmbeddedDocumentList like in:

class Client(me.EmbeddedDocument):
    name = me.StringField()

class Doc(me.Document):
    clients = me.EmbeddedDocumentListField(Client)

d = Doc(clients=[Client(name='John')]).save()
d.clients.filter(name='John')           # Out: [<Client: Client object>]
d.clients.filter(name__icontains='J')       # raises AttributeError: 'Client' object has no attribute 'name__icontains'

That EmbeddedDocumentList.filter does not support operators like __gte, __lte, __icontains, etc, it only supports simple comparison. I understand that users can get confused with the queryset.filter that has those fancy operators. Implementing those operators here would be overkill, I see 2 options:

  • Improve the doc of the EmbeddedDocumentList.filter and mention that it does not supports fancy operator like queryset.filter
  • Get rid of EmbeddedDocumentList.filter, I believe we should do this on the long run because the benefits of this method are limited and its confusing with queryset.filter (Just my opinion :))

I'll push a PR to improve the doc shortly

@erdenezul Hi Sorry Couldn't reply soon. But What i meant is what @bagerard has explained in reply. Filter on ebeddeddocumentlist doesn't support those fancy operators. i was wondering if we could some how enable them.

@bagerard It doesn't make sense to drop an already existing enriched feature in contrast to bettering the existing feature's functionality.

The querset.objects() operators like __gte, __lte are relying on mongodb's corresponding operators whereas the EmbeddedDocumentList.filter is a pure python implementation so it would mean mimicking the behavior (and edge cases) of the mongodb operators. Personally I'm not in favor of it but that's not my call :)

What we could do is leave this one closed and create another ticket with proper name that would be labeled as "feature request" and reference this ticket into the new one.

https://docs.mongodb.com/manual/reference/method/Bulk.find.arrayFilters/ would do the trick but it is very new feature in MongoDB 3.6

Was this page helpful?
0 / 5 - 0 ratings