Частичный поиск слов не работает в elasticsearch (elasticsearch-py) с использованием mongo-connector

В настоящее время я проиндексировал свою коллекцию mongoDB в Elasticsearch, работающем в контейнере докеров. Я могу запросить документ по его точному имени, но Elasticsearch не может сопоставить запрос, если это только часть имени. Вот пример:

>>> es = Elasticsearch('0.0.0.0:9200')
>>> es.indices.get_alias('*')
{'mongodb_meta': {'aliases': {}}, 'sigstore': {'aliases': {}}, 'my-index': {'aliases': {}}}
>>> x = es.search(index='sigstore', body={'query': {'match': {'name': 'KEGG_GLYCOLYSIS_GLUCONEOGENESIS'}}})
>>> x
{'took': 198, 'timed_out': False, '_shards': {'total': 1, 'successful': 1, 'skipped': 0, 'failed': 0}, 'hits': {'total': {'value': 1, 'relation': 'eq'}, 'max_score': 8.062855, 'hits': [{'_index': 'sigstore', '_type': 'sigs', '_id': '5d66c23228144432307c2c49', '_score': 8.062855, '_source': {'id': 1, 'name': 'KEGG_GLYCOLYSIS_GLUCONEOGENESIS', 'description': 'http://www.broadinstitute.org/gsea/msigdb/cards/KEGG_GLYCOLYSIS_GLUCONEOGENESIS', 'members': ['ACSS2', 'GCK', 'PGK2', 'PGK1', 'PDHB', 'PDHA1', 'PDHA2', 'PGM2', 'TPI1', 'ACSS1', 'FBP1', 'ADH1B', 'HK2', 'ADH1C', 'HK1', 'HK3', 'ADH4', 'PGAM2', 'ADH5', 'PGAM1', 'ADH1A', 'ALDOC', 'ALDH7A1', 'LDHAL6B', 'PKLR', 'LDHAL6A', 'ENO1', 'PKM2', 'PFKP', 'BPGM', 'PCK2', 'PCK1', 'ALDH1B1', 'ALDH2', 'ALDH3A1', 'AKR1A1', 'FBP2', 'PFKM', 'PFKL', 'LDHC', 'GAPDH', 'ENO3', 'ENO2', 'PGAM4', 'ADH7', 'ADH6', 'LDHB', 'ALDH1A3', 'ALDH3B1', 'ALDH3B2', 'ALDH9A1', 'ALDH3A2', 'GALM', 'ALDOA', 'DLD', 'DLAT', 'ALDOB', 'G6PC2', 'LDHA', 'G6PC', 'PGM1', 'GPI'], 'user': '[email protected]', 'type': 'public', 'level1': 'test', 'level2': 'test2', 'time': '08-28-2019 14:03:29 EDT-0400', 'source': 'File', 'mapped': [''], 'notmapped': [''], 'organism': 'human'}}]}}

При использовании полного имени документа elasticsearch может успешно запросить его. Но вот что происходит, когда я пытаюсь выполнить поиск по части имени или использовать подстановочный знак:

>>> x = es.search(index='sigstore', body={'query': {'match': {'name': 'KEGG'}}})
>>> x
{'took': 17, 'timed_out': False, '_shards': {'total': 1, 'successful': 1, 'skipped': 0, 'failed': 0}, 'hits': {'total': {'value': 0, 'relation': 'eq'}, 'max_score': None, 'hits': []}}



>>> x = es.search(index='sigstore', body={'query': {'match': {'name': 'KEGG*'}}})
>>> x
{'took': 3, 'timed_out': False, '_shards': {'total': 1, 'successful': 1, 'skipped': 0, 'failed': 0}, 'hits': {'total': {'value': 0, 'relation': 'eq'}, 'max_score': None, 'hits': []}}

В дополнение к настройкам индекса по умолчанию я также попытался создать индекс, который позволяет использовать токенизатор nGram, чтобы я мог выполнять частичный поиск, но это также не сработало. Вот настройки, которые я использовал для этого индекса:

{
  "sigstore": {
    "aliases": {},
    "mappings": {},
    "settings": {
      "index": {
        "max_ngram_diff": "99",
        "number_of_shards": "1",
        "provided_name": "sigstore",
        "creation_date": "1579200699718",
        "analysis": {
          "filter": {
            "substring": {
              "type": "nGram",
              "min_gram": "1",
              "max_gram": "20"
            }
          },
          "analyzer": {
            "str_index_analyzer": {
              "filter": [
                "lowercase",
                "substring"
              ],
              "tokenizer": "keyword"
            },
            "str_search_analyzer": {
              "filter": [
                "lowercase"
              ],
              "tokenizer": "keyword"
            }
          }
        },
        "number_of_replicas": "1",
        "uuid": "3nf915U6T9maLdSiJozvGA",
        "version": {
          "created": "7050199"
        }
      }
    }
  }
}

и это соответствующая команда python, которая его создала:

es.indices.create(index='sigstore',body={"mappings": {},"settings": { 'index': { "analysis": {"analyzer": {"str_search_analyzer": {"tokenizer": "keyword","filter": ["lowercase"]},"str_index_analyzer": {"tokenizer": "keyword","filter": ["lowercase", "substring"]}},"filter": {"substring": {"type": "nGram","min_gram": 1,"max_gram": 20}}}},'max_ngram_diff': '99'}})

Я использую mongo-connector в качестве конвейера между моей коллекцией mongoDB и elasticsearch. Вот команда, которую я использую для его запуска:

mongo-connector -m mongodb://username:[email protected]:27017/?authSource=admin -t elasticsearch:9200 -d elastic2_doc_manager -n sigstore.sigs

Я не уверен, почему мой elasticsearch не может получить частичное совпадение, и мне интересно, есть ли какой-то параметр, который мне не хватает, или есть какая-то критическая ошибка, которую я где-то сделал. Спасибо за прочтение.

Версии

MongoDB 4.0.10

elasticsearch == 7.1.0

elastic2-doc-manager [elastic5]


person najitaleb    schedule 16.01.2020    source источник
comment
Привет, Вы установили str_search_analyzer в настройках, но не устанавливаете отображение! Можете ли вы предоставить отображение вашего индекса? Я уверен, что все ваши поля отображаются как ключевые слова, поэтому работает только точное соответствие. Подробнее о том, как настроить сопоставление: эластичный. co / guide / en / elasticsearch / reference / 7.5 /.   -  person Gabriel    schedule 17.01.2020
comment
Привет, Габриэль. Спасибо, что посмотрели. Вот суть отображений индекса. gist.github.com/najitaleb/5c778b098d10ffd69e4eb36de2b6947b, я просматриваю эту страницу Я не уверен, какие из этих опций мне нужно изменить. Это будет expand_wildcards?   -  person najitaleb    schedule 17.01.2020
comment
Вообще-то, мне кажется, я понимаю, о чем вы сейчас говорите. Должен ли я переключить тип поля «имя» с ключевого слова на текст? Позволит ли это мне искать слова только по части слова?   -  person najitaleb    schedule 17.01.2020
comment
Я изменил некоторые настройки, но совпадения все еще нет. Вот мои текущие сопоставления и настройки: gist.github.com/najitaleb/11798f1b6cc95112c35a   -  person najitaleb    schedule 17.01.2020


Ответы (1)


Обновлено после проверки вашей сути:

Вам необходимо применить сопоставление к своему полю, как написано в документе, см. Первую ссылку, которой я делюсь в комментарии.

Это необходимо сделать после применения настроек к вашему индексу в соответствии с сутью строки 11.

Что-то вроде:

PUT /your_index/_mapping
{
  "properties": {
    "name": {
      "type": "keyword",
      "ignore_above": 256,
      "fields": {
        "str_search_analyzer": {
          "type": "text",
          "analyzer": "str_search_analyzer"
        }
      }
    }
  }
}

После того, как вы установили сопоставление, необходимо применить его к вашему документу, используя update_by_query

https://www.elastic.co/guide/en/elasticsearch/reference/master/docs-update-by-query.html.

Таким образом, вы можете продолжить поиск с поиском терминов по имени вашего поля, поскольку оно будет проиндексировано с сопоставлением ключевых слов (точное совпадение) и по sub_field name.str_search_analyzer с частью слова.

your_keyword = 'KEGG_GLYCOLYSIS_GLUCONEOGENESIS' OR 'KEGG*'

x = es.search(index='sigstore', body={'query': {'bool': {'should':[{'term':  {'name': your_keyword}},
{'match': {'name.str_search_analyzer': your_keyword}}
]}}
})
person Gabriel    schedule 20.01.2020
comment
Спасибо за ответ, Габриэль. Я попытался ввести параметры, которые вы мне дали, и снова попытаться выполнить поиск, но все еще не уверен, почему ваше предложение не сработало. Я добавил суть шагов, которые я предпринял для реализации вашего ответа, но я все еще получаю 0 совпадений. gist.github.com/najitaleb/cdf6a8aa0363580f0841e2dacec859dacec859d - person najitaleb; 21.01.2020
comment
Я обновил ответ и ответ в вашей сути. Вам необходимо обновить сопоставление и переиндексировать ваши данные, чтобы применить изменения, ИЛИ вам нужно удалить свои данные и снова проиндексировать, чтобы ваши данные были проиндексированы с правильным сопоставлением. - person Gabriel; 22.01.2020
comment
Привет, здорово, что вы можете заставить его работать, и, конечно, если я смогу помочь, я помогу :) Вы можете проверить API-интерфейс анализа, он поможет вам отладить и построить свой анализатор, чтобы он работал с вашим запросом поиска. elastic.co/guide/en/ elasticsearch / ссылка / 7.5 / - person Gabriel; 23.01.2020