Elasticsearch-dsl-py: Document.search fails when using custom index= value

Created on 29 May 2019  路  4Comments  路  Source: elastic/elasticsearch-dsl-py

Using

elasticsearch==6.4.0
elasticsearch-dsl==6.4.0

given a Document subclass called Profile, the following code fails

>>> connection = connections.create_connection('default', hosts=['elasticsearch'])
>>> Profile.search(index='default', using=connection).execute()
Traceback (most recent call last):
  File "/usr/local/lib/python3.7/code.py", line 90, in runcode
    exec(code, self.locals)
  File "<console>", line 1, in <module>
  File "/srv/venv/lib/python3.7/site-packages/elasticsearch_dsl/response/__init__.py", line 25, in __repr__
    return '<Response: %r>' % (self.hits or self.aggregations)
  File "/srv/venv/lib/python3.7/site-packages/elasticsearch_dsl/response/__init__.py", line 47, in hits
    hits = AttrList(map(self._search._get_result, h['hits']))
  File "/srv/venv/lib/python3.7/site-packages/elasticsearch_dsl/utils.py", line 38, in __init__
    l = list(l)
  File "/srv/venv/lib/python3.7/site-packages/elasticsearch_dsl/search.py", line 221, in _get_result
    if hasattr(doc_type, '_matches') and doc_type._matches(hit):
  File "/srv/venv/lib/python3.7/site-packages/elasticsearch_dsl/document.py", line 117, in _matches
    return fnmatch(hit.get('_index', ''), cls._index._name) \
  File "/usr/local/lib/python3.7/fnmatch.py", line 35, in fnmatch
    pat = os.path.normcase(pat)
  File "/usr/local/lib/python3.7/posixpath.py", line 54, in normcase
    s = os.fspath(s)
TypeError: expected str, bytes or os.PathLike object, not NoneType

this happens when index is passed to search as a param and Profile.Index is not set (which in our case it can't be as there are multiple indices that are used with this document type).

I did some digging in the code and it seems that when Request._get_result calls the Document._matches method it does not pass the index name, the document method always uses cls._index._name which is None.

If I understand this code correctly then even if Profile.Index was set to something, it would still not work correctly when index is overwritten via search param since the values could be different.

So far our workaround was to override the _matches method and get rid of that comparison on index name, but I guess it was there for a reason so that probably breaks some use case, though I'm not sure what that could be -- if anyone could shed some light on this that would help.

bug

Most helpful comment

Thanks again for the report, @vanzi, the fix will go out with the next release.

All 4 comments

Thank you for the report, this indeed looks like a bug. The workaround you have makes perfect sense.

If you override index the current logic would still work when the index name on the document is set to a wildcard, which is what you would most likely do in that case - have for example multiple indices for profiles like profile-default and profile-special and your profile class would then be:

class Profile(Document):
  class Index:
    name = "profile-*"

Thanks again for the report, @vanzi, the fix will go out with the next release.

@HonzaKral
I got exactly same problem with python 3.7, using
elasticsearch==7.0.0 elasticsearch-dsl==7.0.0

@monomonedula that was my bad, I fixed the code but haven't done a release since then. Just released 7.1.0 containing the fix. Apologies for the delay!

Was this page helpful?
0 / 5 - 0 ratings