Я недавно начал использовать ElasticSearch, и мне кажется, что я не могу заставить его искать часть слова.
Пример: у меня есть три документа из моей couchdb, проиндексированных в ElasticSearch:
{
"_id" : "1",
"name" : "John Doeman",
"function" : "Janitor"
}
{
"_id" : "2",
"name" : "Jane Doewoman",
"function" : "Teacher"
}
{
"_id" : "3",
"name" : "Jimmy Jackal",
"function" : "Student"
}
Итак, теперь я хочу найти все документы, содержащие "Doe"
curl http://localhost:9200/my_idx/my_type/_search?q=Doe
Это не возвращает ни одного попадания. Но если я буду искать
curl http://localhost:9200/my_idx/my_type/_search?q=Doeman
Он действительно возвращает один документ (Джон Доеман).
Я пробовал устанавливать разные анализаторы и разные фильтры в качестве свойств моего индекса. Я также пробовал использовать полноценный запрос (например:
{
"query": {
"term": {
"name": "Doe"
}
}
}
) Но вроде ничего не работает.
Как сделать так, чтобы ElasticSearch находил и Джона Доемана, и Джейн Доу-женщина, когда я ищу "Доу"?
ОБНОВИТЬ
Я попытался использовать токенизатор и фильтр nGram, как предложил Игорь, вот так:
{
"index": {
"index": "my_idx",
"type": "my_type",
"bulk_size": "100",
"bulk_timeout": "10ms",
"analysis": {
"analyzer": {
"my_analyzer": {
"type": "custom",
"tokenizer": "my_ngram_tokenizer",
"filter": [
"my_ngram_filter"
]
}
},
"filter": {
"my_ngram_filter": {
"type": "nGram",
"min_gram": 1,
"max_gram": 1
}
},
"tokenizer": {
"my_ngram_tokenizer": {
"type": "nGram",
"min_gram": 1,
"max_gram": 1
}
}
}
}
}
Проблема, с которой я столкнулся сейчас, заключается в том, что каждый запрос возвращает ВСЕ документы. Есть указатели? Документация ElasticSearch по использованию nGram невелика ...
Ответы:
Я тоже использую nGram. Я использую стандартный токенизатор и nGram просто как фильтр. Вот моя установка:
Вы можете найти части слова до 50 букв. Настройте max_gram, как вам нужно. В немецком языке слова могут быть очень большими, поэтому я установил высокое значение.
источник
Поиск с использованием подстановочных знаков в начале и в конце будет очень медленным для большого индекса. Если вы хотите иметь возможность поиска по префиксу слова, удалите ведущий подстановочный знак. Если вам действительно нужно найти подстроку в середине слова, вам лучше использовать токенизатор ngram.
источник
Я думаю, что никаких карт менять не нужно. Попробуйте использовать query_string , это прекрасно. Все сценарии будут работать со стандартным анализатором по умолчанию:
У нас есть данные:
Сценарий 1:
Отклик:
Сценарий 2:
Отклик:
Сценарий 3:
Отклик:
РЕДАКТИРОВАТЬ - та же реализация с эластичным поиском данных Spring https://stackoverflow.com/a/43579948/2357869
Еще одно объяснение, почему query_string лучше других https://stackoverflow.com/a/43321606/2357869
источник
без изменения сопоставлений индексов вы можете выполнить простой префиксный запрос, который будет выполнять частичный поиск, как вы надеетесь
то есть.
https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-prefix-query.html
источник
Попробуйте решение, описанное здесь: Точный поиск подстроки в ElasticSearch
Чтобы решить проблему использования диска и проблему слишком длинного поискового запроса , используются короткие 8- значные нграммы (сконфигурированные с: "max_gram": 8 ). Для поиска терминов, содержащих более 8 символов, превратите поиск в логический запрос AND, ищущий каждую отдельную 8-символьную подстроку в этой строке. Например, если пользователь искал большой двор (строка из 10 символов), поиск был бы таким:
"АРГЭ Я И АРГЕ ЯР И ГОРОД .
источник
min_gram
иmax_gram
кажется, что это будет линейно зависеть от размера значений поля и диапазонаmin
иmax
. Насколько недовольны использованием чего-то подобного?ngram
которой это фильтр над токенизатором? не могли бы вы просто использовать его как токенизатор, а затем применить фильтр нижнего регистра ...index_ngram: { type: "custom", tokenizer: "ngram_tokenizer", filter: [ "lowercase" ] }
Я попробовал, и, похоже, он дает те же результаты, используя тестовый api анализатораЕсли вы хотите реализовать функцию автозаполнения, советник завершения - самое удобное решение. Следующая запись в блоге содержит очень четкое описание того, как это работает.
В двух словах, это структура данных в памяти, называемая FST, которая содержит действительные предложения и оптимизирована для быстрого поиска и использования памяти. По сути, это просто график. Например, и FST , содержащее слово
hotel
,marriot
,mercure
,munchen
иmunich
будет выглядеть следующим образом :источник
вы можете использовать regexp.
если вы используете этот запрос:
вам будут предоставлены все данные, имена которых начинаются с "J". Предположим, вы хотите получить только первые две записи, имена которых заканчиваются на "man", чтобы вы могли использовать этот запрос:
и если вы хотите получить все записи, которые в их имени существуют "m", вы можете использовать этот запрос:
Это работает для меня. И я надеюсь, что мой ответ подойдет для решения вашей проблемы.
источник
Использование wildcards (*) предотвращает подсчет очков
источник
Я использую это, и я работал
источник
Неважно.
Мне пришлось посмотреть документацию Lucene. Кажется, я могу использовать подстановочные знаки! :-)
делает свое дело!
источник