Elasticsearch проверяет, существует ли подмножество слов

Я пытаюсь найти слово, которое является подмножеством заданного слова. Например, если я ищу слово "localhost.testsite.com", я должен получить результаты, содержащие "testsite.com". Я знаю, что мы можем сделать наоборот с подстановочными знаками, но трудно найти пример с моим требованием.

Вот что я пытаюсь:

GET domains/_search
{
  "from": 0," size": 25,
    "query": 
    {
      "bool": 
      {
        "must": [
          {
            "match": {
              "domain": "localhost.testsite.com"
            }
          }
        ]
      }
    }
}

Но это соответствует всему слову. Кто-нибудь знает, как запросить, чтобы он проверял подмножества, такие как "testsite.com"?


person SSen    schedule 14.06.2019    source источник


Ответы (1)


Вам необходимо создать собственный анализатор, который использует char filter, чтобы заменить . на space.

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

{
    "settings": {
        "analysis": {
            "analyzer": {
                "my_analyzer": {
                    "tokenizer": "standard",
                    "char_filter": [
                        "replace_dots"
                    ]
                }
            },
            "char_filter": {
                "replace_dots": {
                    "type": "mapping",
                    "mappings": [
                        ". => \\u0020"
                    ]
                }
            }
        }
    }
}

Этот анализатор создаст следующие токены для поля, содержащего testsite.com

{
    "tokens": [
        {
            "token": "testsite",
            "start_offset": 0,
            "end_offset": 8,
            "type": "<ALPHANUM>",
            "position": 0
        },
        {
            "token": "com",
            "start_offset": 9,
            "end_offset": 12,
            "type": "<ALPHANUM>",
            "position": 1
        }
    ]
}

Теперь вам нужно использовать запрос match в том же поле, так как запрос соответствия анализируется и использует тот же анализатор, поэтому для текста поиска localhost.testsite.com ниже будут созданы токены.

{
    "tokens": [
        {
            "token": "localhost",
            "start_offset": 0,
            "end_offset": 9,
            "type": "<ALPHANUM>",
            "position": 0
        },
        {
            "token": "testsite",
            "start_offset": 10,
            "end_offset": 18,
            "type": "<ALPHANUM>",
            "position": 1
        },
        {
            "token": "com",
            "start_offset": 19,
            "end_offset": 22,
            "type": "<ALPHANUM>",
            "position": 2
        }
    ]
}

Теперь, когда ваш документ содержит токены testsite и com, он появится в результатах поиска.

Дайте мне знать, если вам нужна помощь в понимании этого.

EDIT: – Несколько ссылок для понимания процесса анализа https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis.html

person user156327    schedule 14.06.2019
comment
Спасибо Амит. Но я запускаю запрос в лямбде Python. Так что не хотелось бы усложнять. Разве нет другого пути? - person SSen; 17.06.2019
comment
@SSen, извини, чувак, но встроенного анализатора для решения твоей проблемы нет. - person user156327; 17.06.2019
comment
Ok. Можно ли создать собственный анализатор для существующего индекса? - person SSen; 17.06.2019
comment
да, но все же вам нужно переиндексировать все данные, так как это критическое изменение, а переиндексация принесет в индекс только последние токены на основе нового анализатора. - person user156327; 17.06.2019
comment
@SSen, дайте мне знать, смогли ли вы решить проблему? - person user156327; 17.06.2019
comment
Можете ли вы сообщить мне, приведет ли переиндексация всех данных к удалению всех существующих записей? - person SSen; 20.06.2019
comment
@SSen, да, все существующие записи должны быть удалены и созданы заново, чтобы новый анализатор токенизировал значения в соответствии с вашими изменениями в вашем индексе. Вы также можете взглянуть на stackoverflow.com/questions /46806222/ и дайте мне знать, если у вас возникнут дополнительные вопросы, также не забудьте проголосовать и принять мой ответ, как только вы найдете решение :-) - person user156327; 20.06.2019
comment
Спасибо за ваш быстрый ответ. Я бы определенно поддержал ваш ответ, потому что это один из способов сделать это. Но мне нужно иметь возможность работать с существующим индексом, не теряя в нем никаких данных. Поэтому мне пришлось справиться с этим со стороны лямбда, и это работает. - person SSen; 21.06.2019
comment
@SSen, не могли бы вы объяснить, как вы справляетесь с этим, используя лямбда, и вы все еще меняли анализатор? было бы интересно узнать об этом, может быть, вы можете написать ответ, объясняющий это, чтобы мы также могли учиться у вас :-) - person user156327; 21.06.2019
comment
Я не вносил никаких изменений в анализатор, потому что работаю над существующим индексом. Я выбрал все домены, которые мне нужно было рассмотреть, а затем проверил, существует ли какой-либо домен в домене, который я передаю. Возможно, это не лучший подход, но не могу придумать ничего лучше. - person SSen; 25.06.2019
comment
@SSen, это конечно способ, но не самый лучший и быстрый, и вы не используете ES для поиска :).. Я бы посоветовал вам создать еще одно поле и добавить этот анализатор, и с его помощью вы можете начать индексировать новые данные как свои постепенное изменение.. таким образом будет работать хотя бы новый документ, и всякий раз, когда обновляется старый документ, этот документ также будет иметь последний токен и будет включен в ваш результат поиска, на другое вы можете ссылаться elastic.co/guide/en/elasticsearch/reference/current/ для переиндексации без простоев и ее достаточно быстро. - person user156327; 17.12.2019
comment
@SSen Не могли бы вы принять и проголосовать за мой ответ, поскольку он решает ваш запрос, это поможет сообществу легко найти ответы, а также дайте мне знать, если у вас есть дополнительный вопрос? - person user156327; 23.01.2020