# Поиск фразы в индексе со стеммингом

**URL:** https://discuss.elastic.co/t/topic/74031
**Category:** Вопросы на русском языке
**Created:** [February 6, 2017, 9:22am UTC](https://discuss.elastic.co/t/topic/74031 "2017-02-06T09:22:22Z")
**Posts on this page:** 13
**Page:** 1

<div class="post-metadata">

### Author: ![GreenX](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/greenx/32/51751_2.png) [@GreenX](https://discuss.elastic.co/u/GreenX)
#### Post date: [February 6, 2017, 9:22am UTC](https://discuss.elastic.co/t/topic/74031/1 "2017-02-06T09:22:22Z")

</div>

Доброго времени суток!  
Есть индекс и поле в нем построенное со стеммингом.  
Не получается сделать поиск полной фразы.  
Т.е. на пример, надо найти точно "Электронный документ".  
Как ни пытался - ES первым выводит более длинное значение, какой-нибудь "Справочник по электронному документообороту".  
Возможно ли это побороть или переделывать индексы?  
А если переделывать как правильно?  
Ведь получается, что нужны и полные слова и "обрезки".  
Целые для поиска точных фраз и обрезки для всяких не точных поисков.  
Или вообще по другому делается?

---

<div class="post-metadata">

### Author: ![Igor\_Motov](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/igor_motov/32/45193_2.png) [@Igor\_Motov](https://discuss.elastic.co/u/Igor_Motov)
#### Post date: [February 6, 2017, 4:28pm UTC](https://discuss.elastic.co/t/topic/74031/2 "2017-02-06T16:28:18Z")

</div>

Обычно, в таких случаях поле индексируют дважды - один раз как со стемингом и синонимами и второй раз без. Поиск осуществляется по обоим полям с бустом. Примеры можно [в этой презентации](https://imotov.github.io/presentations/you-know-for-search.html#/6/11) посмотреть.

---

<div class="post-metadata">

### Author: ![GreenX](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/greenx/32/51751_2.png) [@GreenX](https://discuss.elastic.co/u/GreenX)
#### Post date: [February 6, 2017, 4:51pm UTC](https://discuss.elastic.co/t/topic/74031/3 "2017-02-06T16:51:05Z")

</div>

Отлично! Большое спасибо. В приведенном примере my\_type сразу два аналайзера применяется, дополнительных движений не нужно?

---

<div class="post-metadata">

### Author: ![Igor\_Motov](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/igor_motov/32/45193_2.png) [@Igor\_Motov](https://discuss.elastic.co/u/Igor_Motov)
#### Post date: [February 6, 2017, 4:53pm UTC](https://discuss.elastic.co/t/topic/74031/4 "2017-02-06T16:53:37Z")

</div>

> [@GreenX](#):
>
> В приведенном примере my\_type сразу два аналайзера применяется, дополнительных движений не нужно?

Нужно. Запрос на следующем слайде.

---

<div class="post-metadata">

### Author: ![GreenX](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/greenx/32/51751_2.png) [@GreenX](https://discuss.elastic.co/u/GreenX)
#### Post date: [February 6, 2017, 5:17pm UTC](https://discuss.elastic.co/t/topic/74031/5 "2017-02-06T17:17:38Z")

</div>

Ну про это то я догадался 🙂  
Я имел ввиду, что при индексации не надо данные в два поля посылать:  
put /my\_index/my\_type  
{ "my\_text": "some text",  
"my\_text.with\_synonyms": "some text"  
}

---

<div class="post-metadata">

### Author: ![Igor\_Motov](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/igor_motov/32/45193_2.png) [@Igor\_Motov](https://discuss.elastic.co/u/Igor_Motov)
#### Post date: [February 6, 2017, 5:33pm UTC](https://discuss.elastic.co/t/topic/74031/6 "2017-02-06T17:33:15Z")

</div>

> [@GreenX](#):
>
> Я имел ввиду, что при индексации не надо данные в два поля посылать:

Да, оба поля будет созданы автоматически из одного поля исходного документа.

---

<div class="post-metadata">

### Author: ![GreenX](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/greenx/32/51751_2.png) [@GreenX](https://discuss.elastic.co/u/GreenX)
#### Post date: [February 9, 2017, 6:50pm UTC](https://discuss.elastic.co/t/topic/74031/7 "2017-02-09T18:50:25Z")

</div>

А имеет смысл вырезать стоп слова из оригинальных токенов (без синонимов)?

---

<div class="post-metadata">

### Author: ![Igor\_Motov](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/igor_motov/32/45193_2.png) [@Igor\_Motov](https://discuss.elastic.co/u/Igor_Motov)
#### Post date: [February 10, 2017, 12:53am UTC](https://discuss.elastic.co/t/topic/74031/8 "2017-02-10T00:53:24Z")

</div>

Я, лично, стоп слова недолюбливаю. Считаю вреда от них больше чем пользы, особенное, если бездумно брать готовый список слов от куда-нибудь. Стандартный список русских стоп слов [тут](https://github.com/apache/lucene-solr/blob/master/lucene/analysis/common/src/resources/org/apache/lucene/analysis/snowball/russian_stop.txt), например. С моей точки зрения, он слишком большой, и зачем туда такие слова, как `человек` и `жизнь` засунули - я просто ума не приложу. К тому-же без стемминга такой список стоп слов в русском бесполезен - так как слова в нем заданы только в одной форме.

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

---

<div class="post-metadata">

### Author: ![GreenX](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/greenx/32/51751_2.png) [@GreenX](https://discuss.elastic.co/u/GreenX)
#### Post date: [February 10, 2017, 8:27am UTC](https://discuss.elastic.co/t/topic/74031/9 "2017-02-10T08:27:55Z")

</div>

Я поэтому и спрашиваю, что пресловутое "быть или не быть", как фразу не найти.  
Вот и выходит, что первый индекс должен быть просто "standard", а второй более хитрый.  
И пока я думаю, что должен стандартный токенайзер, а дальше фильты  
lowcase -\>stop\_word -\> keyword -\> russian\_morphology -\> engilish\_morphlogy -\> synonym

1. lowcase - чтобы потом не заботиться о регистре написания
2. stop\_word. - т.к. они в первом индексе есть тут их можно нещадно резать.
3. keyword - для всяких исключений и сокращений: СССР, КГБ, ЯрГУ
4. russian\_morphology - как минимум, мне не понравилось как стеммер swonball с русскими фамилиями работает.
5. engilish\_morphlogy - до кучи
6. synonym - синонимы в нормальной форме.

Есть конечно еще некоторые сомнения:

1. Резать ли цифры? Их же много. Но ведь найдется гений, который будет искать организацию по ИНН.
2. Нужны ли nGram-ы для всяких нечетких поисков. Если нужны то получается, нужно делать третий индекс. Ибо по опыту сочетание стеммера и nGram даёт не однозначный результат.

В общем, если есть мудрость поделитесь 🙂  
Понятно, что у всех свои нюансы, но ведь есть общие принципы которые подойдут 98%% задач по поиску в русском тексте.

---

<div class="post-metadata">

### Author: ![Igor\_Motov](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/igor_motov/32/45193_2.png) [@Igor\_Motov](https://discuss.elastic.co/u/Igor_Motov)
#### Post date: [February 10, 2017, 3:51pm UTC](https://discuss.elastic.co/t/topic/74031/10 "2017-02-10T15:51:40Z")

</div>

Как я пытался объяснить в предыдущем сообщении `stop_word` перед стеммером работать не будет, если только вы все возможные словоформы для каждой лексемы туда на добавите. Поэтому обычно делают так `lowercase -> keyword -> russian_morphology -> engilish_morphlogy -> stop_word -> synonym`

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

2. Да, nGram со стеммером применять бессмысленно, так как они и тот и другой выполняет по-сути одну и туже функцию. Если поиск по подстрокам нужен, лучше проиндексировать еще раз.

---

<div class="post-metadata">

### Author: ![GreenX](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/greenx/32/51751_2.png) [@GreenX](https://discuss.elastic.co/u/GreenX)
#### Post date: [February 15, 2017, 8:15pm UTC](https://discuss.elastic.co/t/topic/74031/11 "2017-02-15T20:15:25Z")

</div>

> [@Igor\_Motov](#):
>
> Как я пытался объяснить в предыдущем сообщении `stop_word` перед стеммером работать не будет, если только вы все возможные словоформы для каждой лексемы туда на добавите. Поэтому обычно делают так `lowercase -> keyword -> russian_morphology -> engilish_morphlogy -> stop_word -> synonym`

До редактирования поста так и было 🙂  
А потом пришла такая мысль:

1. Составить достаточно полный словарь задача посильная.
2. Сложность зависит (почти) только от объема входных данных
3. Если количество stop слов 30%, то объем на выходе на треть меньше.
4. Поэтому вырезать сразу лишнее интереснее.

> [@Igor\_Motov](#):
>
> ....  
> 2. Да, nGram со стеммером применять бессмысленно, так как они и тот и другой выполняет по-сути одну и туже функцию. Если поиск по подстрокам нужен, лучше проиндексировать еще раз.

Получается, что если нужен поиск по подстрокам, то нет смысла вообще связываться со стеммером и морфологическим разбором?

---

<div class="post-metadata">

### Author: ![Igor\_Motov](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/igor_motov/32/45193_2.png) [@Igor\_Motov](https://discuss.elastic.co/u/Igor_Motov)
#### Post date: [February 15, 2017, 8:54pm UTC](https://discuss.elastic.co/t/topic/74031/12 "2017-02-15T20:54:13Z")

</div>

> [@GreenX](#):
>
> Получается, что если нужен поиск по подстрокам, то нет смысла вообще связываться со стеммером и морфологическим разбором?

Для меня это взаимозаменяемые решения. Выбор решения зависит от типа и объема данных (ngrams производят больше токенов и размер индекса, как правило получается больше) и предпочтений пользователей (некоторые пользователи предпочитают подстроки, потому что им так проще понять почему они получили тот или иной результат).

---

<div class="post-metadata">

### Author: ![system](https://us1.discourse-cdn.com/elastic/original/3X/1/a/1ac57faf039f6b580b3f104ef42a2a89e41014de.png) [@system](https://discuss.elastic.co/u/system)
#### Post date: [March 15, 2017, 8:55pm UTC](https://discuss.elastic.co/t/topic/74031/13 "2017-03-15T20:55:12Z")

</div>

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.
