Как настроить фильтр токенов синонимов с ElasticSearch-dsl в python? - PullRequest
1 голос
/ 04 мая 2020

Я пытаюсь создать фильтр токенов синонимов с ElasticSearch-dsl в python, чтобы, например, при попытке поиска «крошечный» или «маленький», он также возвращал статьи, включая «маленький». Вот мой код:

from elasticsearch_dsl import token_filter

# Connect to local host server
connections.create_connection(hosts=['127.0.0.1'])

spelling_tokenfilter = token_filter(
    'my_tokenfilter', # Name for the filter
    'synonym', # Synonym filter type
    synonyms_path = "analysis/wn_s.pl"
    )

# Create elasticsearch object
es = Elasticsearch()

text_analyzer = analyzer('my_tokenfilter',
                         type='custom',
                         tokenizer='standard',
                         filter=['lowercase', 'stop', spelling_tokenfilter])

Я создал папку в es-7.6.2 / config с именем «analysis», загрузил базу данных пролога Wor dnet, скопировал и вставил в нее файл «wn_s.pl». , Но когда я запускаю программу, появляется ошибка:

Traceback (most recent call last):
  File "index.py", line 161, in <module>
    main()
  File "index.py", line 156, in main
    buildIndex()
  File "index.py", line 74, in buildIndex
    covid_index.create()
  File "C:\Anaconda\lib\site-packages\elasticsearch_dsl\index.py", line 259, in create
    return self._get_connection(using).indices.create(index=self._name, body=self.to_dict(), **kwargs)
  File "C:\Anaconda\lib\site-packages\elasticsearch\client\utils.py", line 92, in _wrapped
    return func(*args, params=params, headers=headers, **kwargs)
  File "C:\Anaconda\lib\site-packages\elasticsearch\client\indices.py", line 104, in create
    "PUT", _make_path(index), params=params, headers=headers, body=body
  File "C:\Anaconda\lib\site-packages\elasticsearch\transport.py", line 362, in perform_request
    timeout=timeout,
  File "C:\Anaconda\lib\site-packages\elasticsearch\connection\http_urllib3.py", line 248, in perform_request
    self._raise_error(response.status, raw_data)
  File "C:\Anaconda\lib\site-packages\elasticsearch\connection\base.py", line 244, in _raise_error
    status_code, error_message, additional_info
elasticsearch.exceptions.RequestError: RequestError(400, 'illegal_argument_exception', 'failed to build synonyms')

Кто-нибудь знает, как это исправить? Спасибо!

1 Ответ

1 голос
/ 05 мая 2020

Похоже, это происходит потому, что у вас есть фильтры токенов lowercase и stop, определенные до фильтра синонимов ( документы ):

Elasticsearch будет использовать фильтры токенов перед фильтром синонимов в цепочке токенизатора для анализа записей в файле синонимов. Так, например, если фильтр синонимов размещен после стеммера, тогда стеммер также будет применен к записям синонимов.

Во-первых, давайте попробуем получить более подробную информацию об ошибке, поймав исключение:

>>> text_analyzer = analyzer('my_tokenfilter',
...                          type='custom',
...                          tokenizer='standard',
...                          filter=[
...                              'lowercase', 'stop',
...                              spelling_tokenfilter
...                              ])
>>>
>>> try:
...   text_analyzer.simulate('blah blah')
... except Exception as e:
...   ex = e
...
>>> ex
RequestError(400, 'illegal_argument_exception', {'error': {'root_cause': [{'type': 'illegal_argument_exception', 'reason': 'failed to build synonyms'}], 'type': 'illegal_argument_exception', 'reason': 'failed to build synonyms', 'caused_by': {'type': 'parse_exception', 'reason': 'Invalid synonym rule at line 109', 'caused_by': {'type': 'illegal_argument_exception', 'reason': 'term: course of action analyzed to a token (action) with position increment != 1 (got: 2)'}}}, 'status': 400})

Особенно интересна эта часть:

'reason': 'Недопустимое правило синонима в строке 109', 'reason_by': {'type': 'invalid_argument_exception', 'reason': 'term: ход действия, проанализированный для токена (действия) с приращением позиции! = 1 ( got: 2) '}}}

Это говорит о том, что ему удалось найти файл, но не удалось его проанализировать.

Наконец, если вы удалите эти два фильтра токенов, ошибка исчезает:

text_analyzer = analyzer('my_tokenfilter',
                         type='custom',
                         tokenizer='standard',
                         filter=[
                             #'lowercase', 'stop',
                             spelling_tokenfilter
                             ])
...
>>> text_analyzer.simulate("blah")
{'tokens': [{'token': 'blah', 'start_offset': 0, 'end_offset...}

Документация предлагает использовать фильтр токенов мультиплексора на случай необходимости их объединения.

Надеюсь, это поможет!

...