Elasticsearch-dsl-py: Can't achieve autocomplete

Created on 27 Aug 2017  路  8Comments  路  Source: elastic/elasticsearch-dsl-py

Hello,
I am struggling with autocomplete for a long time.
Simply i am loading list of cities to the elasticsearch, i am printing first index so i am sure that Novinki city exists there. And when I do the execute suggest I receive no completion for text "Novin".
I was refering to official tutorial - http://elasticsearch-dsl.readthedocs.io/en/latest/persistence.html
Can someone give me a tip what I am doing wrong?
Thank you

import json
from elasticsearch_dsl import Search, Index, DocType, Text, Completion
from elasticsearch_dsl.connections import connections


connections.create_connection(hosts=['localhost'])

with open('city_list.json') as json_data:
    cities_json = json.load(json_data)

cities = Index('cities')
cities.delete(ignore=404)
cities.create()


@cities.doc_type
class City(DocType):
    name = Text()
    name_suggest = Completion()
    country = Text()

    class Meta:
        doc_type = 'city'

City.init()

for index, city in enumerate(cities_json['cities']):
    if index == 1:
        print(city) # this prints {'coord': {'lon': 37.666668, 'lat': 55.683334}, 'name': 'Novinki', 'id': 519188, 'country': 'RU'}
    city = City(name=city['name'], country=city['country'])
    city.save()

s = City.search()
s = s.suggest('name_suggestions', 'Novin', completion={'field': 'name_suggest'})
suggestions = s.execute_suggest()
for result in suggestions.name_suggestions:
    print('Suggestions for %s:' % result) # this gives me Suggestions for {'length': 5, 'options': [], 'offset': 0, 'text': 'Novin'}:

All 8 comments

OK, so I figured out that i was missing assigment to the name_suggest field:
city = City(name=city['name'], name_suggest=city['name'], country=city['country'])
The documentation lacks that information & there is no payload in suggestions anymore(still in documentation)

Still I have further question, how can I apply other analyzer to the Completion field? It is not able to do that like it can be in Text field.

Hi, yes, you can pass an analyzer property to the completion field, see https://www.elastic.co/guide/en/elasticsearch/reference/5.6/search-suggesters-completion.html#completion-suggester-mapping for more details.

Hope this helps!

@HonzaKral how to set the analyzer property for Completion field through elasticsearch-dsl API?
Currently, using the Completion field automatically defaults to using the simple analyzer. Once that happens, it is not possible to change it to a different analyzer by directly interacting with Elastic Search as you suggested in your previous comment.

@princessRapunzel the standard way works, just pass it as an argument to the Completion class:

name_suggest = Completion(analyzer=my_analyzer)

my_analyzer can either be an instance of Analyzer (see 0) or a string containing a name of an existing analyzer.

Hope this helps

0 - http://elasticsearch-dsl.readthedocs.io/en/latest/persistence.html#analysis

@HonzaKral, thanks for your prompt reply. I tried to use the standard way i.e passing as an argument, a string containing the name of existing analyzer ("simple").
my_suggestion_tags = Completion(analyzer = "simple")
This attempt fails with the following error--

ElasticAsset.init()
File "C:\Users\kphaltan\Envs\django-env\lib\site-packages\elasticsearch_dsl\document.py", line 147, in init
cls._doc_type.init(index, using)
File "C:\Users\kphaltan\Envs\django-env\lib\site-packages\elasticsearch_dsl\document.py", line 94, in init
self.mapping.save(index or self.index, using=using or self.using)
File "C:\Users\kphaltan\Envs\django-env\lib\site-packages\elasticsearch_dsl\mapping.py", line 79, in save
return index.save()
File "C:\Users\kphaltan\Envs\django-env\lib\site-packages\elasticsearch_dsl\index.py", line 197, in save
body = self.to_dict()
File "C:\Users\kphaltan\Envs\django-env\lib\site-packages\elasticsearch_dsl\index.py", line 163, in to_dict
mappings, analysis = self._get_mappings()
File "C:\Users\kphaltan\Envs\django-env\lib\site-packages\elasticsearch_dsl\index.py", line 149, in _get_mappings
a = mapping._collect_analysis()
File "C:\Users\kphaltan\Envs\django-env\lib\site-packages\elasticsearch_dsl\mapping.py", line 64, in _collect_analysis
d = analyzer.get_analysis_definition()
AttributeError: 'str' object has no attribute 'get_analysis_definition'

Somehow it seems elasticsearch-dsl is not able to get the right analyzer by from the string containing the same of the analyzer
EDIT- Corrected a typo.

My bad, please use:

from elasticsearch_dsl import analyzer
analyzer('keyword')

Indeed works good :+1:
Other connected thing: As far as I read in elasticsearch documentation, completion suggester is prefix based, so if there is "New York" city and I would type "Yo" in suggester field -> It wont suggest me "New York" text.
I read for that purpose better to use other suggester like "Term Suggester" but is it duable in this library?(I didn't find such field in code)

Hi @HonzaKral ,

I tried to use the analyzer argument in the Completion class, but it fails like one of the comments above:

.../elasticsearch_dsl/mapping.py", line 99, in _collect_analysis
    d = analyzer.get_analysis_definition()
AttributeError: 'str' object has no attribute 'get_analysis_definition'

This is my code:

political_party = Text(
    fields={
        'keyword': Keyword(),
        'suggest': Completion(analyzer=analyzer('brazilian')),
    }
)

I've debugged the code and I fixed it adding the _param_defs in the Completion class

 class Completion(Field):
+    _param_defs = {
+        'analyzer': {'type': 'analyzer'},
+    }
     name = 'completion'

I don't know if it is the best approach, but with some guidance I can open a PR.

PS: the elasticsearch-dsl-py version is 6.2.1

Was this page helpful?
0 / 5 - 0 ratings

Related issues

zahir-koradia picture zahir-koradia  路  3Comments

mortada picture mortada  路  3Comments

berinhard picture berinhard  路  3Comments

leoliuxd picture leoliuxd  路  4Comments

njoannin picture njoannin  路  3Comments