Elasticsearch-dsl-py: Shouldn't Hit and AttrDict objects fully respect python dict's API?

Created on 9 Dec 2019  路  3Comments  路  Source: elastic/elasticsearch-dsl-py

Hi, first of all, thanks for your amazing work with this lib. It's really saving me a lot of time in my day to day work. I'm opening this issue because I might have an enhancement suggestion.

The following code works just fine:

>>> results = search.execute()
>>> obj = results[0]                  
>>> type(obj)
<class 'elasticsearch_dsl.response.hit.Hit'>                                                                                                                                                                           
>>> obj.sigId                                                                                                                                                                                                    
198
>>> obj['sigId']                                                                                                                                                                                                 
198

The same is valid for the AttrDict object:

>>> contact = obj.contactPoint[0]                                                                                                                                                                                
>>> type(contact)                                                                                                                                                                                                
<class 'elasticsearch_dsl.utils.AttrDict'>
>>> contact.name                                                                                                                                                                                                 
'MobileLeadNotificationPhone'
>>> contact['name']                                                                                                                                                                                              
'MobileLeadNotificationPhone'

So, the snippet describes the access to the attributes being enable not only as regular attributes but also via the dict-key strategy. Because of that, I though that both Hit and AttrDict objects would be a dict implementation with some attr sugar, so they'd expose a get method such as every dict object. For the second object this is even more reasonable to think because the class name has Dict in it. But was my surprise when I noticed I can't do that:

>>> getattr(obj, 'sigId', '')                                                                                                                                                                                    
198
>>> obj.get('sigId', '')                                                                                                                                                                                         
*** AttributeError: 'Hit' object has no attribute 'get'
>>> getattr(contact, 'name', '')                                                                                                                                                                                 
'MobileLeadNotificationPhone'
>>> contact.get('name', '')                                                                                                                                                                                      
*** AttributeError: 'AttrDict' object has no attribute 'get'

So, what are your thoughts on this? I'm not familiar with the code base to know if doing this is possible, but I feel that it shouldn't be a big deal and will make these objects more coherent with how they're exposing data.

Ps.: I'm using elasticsearch-dsl==7.0.0

Most helpful comment

To anyone who finds this same issue and wants to access the _source of a Hit like a normal Python Dict

>>> response = s.execute()

>>> item = response.hits.hits[0]._source
>>> item.get('name')
*** AttributeError: 'AttrDict' object has no attribute 'get'

>>> item_dict = response.hits.hits[0]._source.to_dict()
>>> item.get('name') ## WORKS!

All 3 comments

Hi, I understand the sentiment behind this request, but ultimately have to deny it. We made a decision at the beginning of the project to try and have as few obstacles for people to use the libraries and having the full dict interface would severely narrow down the available namespace - we frequently see documents with items as a field for example that wouldn't be possible.

Hope this helps!

To anyone who finds this same issue and wants to access the _source of a Hit like a normal Python Dict

>>> response = s.execute()

>>> item = response.hits.hits[0]._source
>>> item.get('name')
*** AttributeError: 'AttrDict' object has no attribute 'get'

>>> item_dict = response.hits.hits[0]._source.to_dict()
>>> item.get('name') ## WORKS!

Alternatively if you want to use dict.items() you can use the obj.to_dict() method

Was this page helpful?
0 / 5 - 0 ratings

Related issues

SalahAdDin picture SalahAdDin  路  4Comments

quasiben picture quasiben  路  4Comments

beanaroo picture beanaroo  路  4Comments

amih90 picture amih90  路  4Comments

abuzakaria picture abuzakaria  路  4Comments