запрос соответствия фразы не работает должным образом - PullRequest
0 голосов
/ 27 декабря 2018

Чтение из эластичной документации:

match_phrase запрос сначала анализирует строку запроса, чтобы создать список терминов.Затем он ищет все термины, но сохраняет только документы, которые содержат все поисковых терминов, в тех же позициях относительно друг друга.

Я настроил свой анализатор на использование edge_ngram с ключевым словом tokenizer:

{
        "index": {
            "number_of_shards": 1,
            "analysis": {
                "filter": {
                    "autocomplete_filter": {
                        "type": "edge_ngram",
                        "min_gram": 1,
                        "max_gram": 20
                    }
                },
                "analyzer": {
                    "autocomplete": {
                        "type": "custom",
                        "tokenizer": "keyword",
                        "filter": [
                            "lowercase",
                            "autocomplete_filter"
                        ]
                    }
                }
            }
        }
    }

Вот класс Java, который используется для индексации:

@Document(indexName = "myindex", type = "program")
@Getter
@Setter
@Setting(settingPath = "/elasticsearch/settings.json")
public class Program {


    @org.springframework.data.annotation.Id
    private Long instanceId;

    @Field(analyzer = "autocomplete",searchAnalyzer = "autocomplete",type = FieldType.String )
    private String name;
}

, если в документе есть следующая фраза "hello world ", этому запросу будет соответствовать следующий запрос:

{
  "match" : {
    "name" : {
      "query" : "ho",
      "type" : "phrase"
    }
  }
}
result : "hello world"

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

мои вопросы:

1 - я не должен иметь 2 условия поиска в edge_ngram / autocomplete для запроса "ho"?(термины должны быть «h» и «ho» соответственно.)

2 - почему «ho» соответствует «hello world», когда все термины в соответствии с определением фразы не совпадают?(термин «ho» не должен совпадать)


update :

на тот случай, если вопрос не ясен.Запрос на совпадение фразы должен анализировать строку в списке терминов, здесь это ho.Теперь у нас будет 2 члена, так как это edge_ngram с 1 min_gram.2 условия: h и ho.в соответствии с эластичным поиском документ должен содержать все поисковых терминов.Однако hello world имеет только h и не имеет ho, так почему я получил здесь совпадение?

Ответы [ 3 ]

0 голосов
/ 28 декабря 2018
  1. Если бы вы могли предоставить полные, работающие примеры для ваших проблем, вам было бы намного легче помочь вам.Например, что-то вроде этого:

    PUT test
    {
      "settings": {
        "number_of_shards": 1,
        "analysis": {
          "filter": {
            "autocomplete_filter": {
              "type": "edge_ngram",
              "min_gram": 1,
              "max_gram": 20
            }
          },
          "analyzer": {
            "autocomplete": {
              "type": "custom",
              "tokenizer": "keyword",
              "filter": [
                "lowercase",
                "autocomplete_filter"
              ]
            }
          }
        }
      },
      "mappings": {
        "_doc": {
          "properties": {
            "name": {
              "type": "text",
              "analyzer": "autocomplete"
            }
          }
        }
      }
    }
    
    PUT test/_doc/1
    {
      "name": "Hello world"
    }
    
    GET test/_search
    {
      "query": {
        "match_phrase": {
          "name": "hello foo"
        }
      }
    }
    
  2. Судя по вашему поисковому запросу, вы используете Elasticsearch 2.x или более раннюю версию.Это мертвая версия - вам действительно нужно обновить.

  3. Я не уверен, что поиск фразы по граммам имеет смысл в комбинации.Чего вы пытаетесь достичь здесь?
  4. Почему это соответствует?Ваш поисковый запрос проходит через тот же анализатор, что и сохраненное вами поле.Поскольку вы определили min_gram: 1, ваш ho будет найден как h и ho.h соответствует h из hello.match или match_phrase не имеет значения здесь с этим анализатором.
0 голосов
/ 28 декабря 2018

Я получил ответ от форумаasticsearch:

Вы используете фильтр токенов edge_ngram.Давайте посмотрим, как ваш анализатор обрабатывает строку запроса "ho".Предполагая, что ваш индекс называется my_index:

GET my_index/_analyze
{
  "text": "ho",
  "analyzer": "autocomplete"
}

Ответ показывает, что на выходе вашего анализатора будет два токена в позиции 0:

{
  "tokens": [
    {
      "token": "h",
      "start_offset": 0,
      "end_offset": 2,
      "type": "word",
      "position": 0
    },
    {
      "token": "ho",
      "start_offset": 0,
      "end_offset": 2,
      "type": "word",
      "position": 0
    }
  ]
}

Что делает Elasticsearchзапрос для двух токенов в одной позиции?Он обрабатывает запрос как «ИЛИ», даже если вы используете тип "phrase".Вы можете видеть это из выходных данных API проверки (который показывает запрос Lucene, в который был записан ваш запрос):

GET my_index/_validate/query?rewrite=true
{
  "query": {
    "match": {
      "name": {
        "query": "ho",
        "type": "phrase"
      }
    }
  }
}

Поскольку и ваш запрос, и ваш документ имеют h в позиции 0, документ станет хитом.

Теперь, как это решить?Вместо токен-фильтра edge_ngram вы можете использовать токенайзер edge_ngram .Этот токенизатор увеличивает позицию каждого выводимого им токена.

Итак, если вы вместо этого создадите свой индекс следующим образом:

PUT my_index
{
  "settings": {
    "number_of_shards": 1,
    "analysis": {
      "tokenizer": {
        "autocomplete_tokenizer": {
          "type": "edge_ngram",
          "min_gram": 1,
          "max_gram": 20
        }
      },
      "analyzer": {
        "autocomplete": {
          "type": "custom",
          "tokenizer": "autocomplete_tokenizer",
          "filter": [
            "lowercase"
          ]
        }
      }
    }
  },
  "mappings": {
    "doc": {
      "properties": {
        "name": {
          "type": "string",
          "analyzer": "autocomplete"
        }
      }
    }
  }
}

Вы увидите, что этот запрос больше не является хитом:

GET my_index/_search
{
  "query": {
    "match": {
      "name": {
        "query": "ho",
        "type": "phrase"
      }
    }
  }
}

Но вот, например, это:

GET my_index/_search
{
  "query": {
    "match": {
      "name": {
        "query": "he",
        "type": "phrase"
      }
    }
  }
}
0 голосов
/ 27 декабря 2018

Если я понимаю ваши вопросы, проблема заключается в токенизаторе, "токенизатор": "ключевое слово", поиск точной фразы и индекса, как один.

Структурированные текстовые токенизаторы

...