# Как обрабатывать фразу из одинаковых слов?

**URL:** <https://discuss.elastic.co/t/topic/87136>\
**Category:** Вопросы на русском языке\
**Created:** [May 25, 2017, 2:08pm UTC](https://discuss.elastic.co/t/topic/87136 "2017-05-25T14:08:48Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![klara](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/klara/32/18440_2.png) [@klara](https://discuss.elastic.co/u/klara)\
**Post date:** [May 25, 2017, 2:08pm UTC](https://discuss.elastic.co/t/topic/87136/1 "2017-05-25T14:08:48Z")

</div>

Задача сделать поиск с запросом из двух одинаковых слов не равносильным поиску из одного.  
То есть, если ищу пор-пор найти клен-клен, а не клен-дуб .

Управлять этим можно с помощью анализаторов и с помощью запросов.  
Анализаторами мне это видится сложнее, есть ли комбинация запросов которая будет искать в документе два одинаковых слова, а не одно?

Или есть ли анализатор, которые индексировал клен-клен как {клен-клен, клен клен}, тогда мне не надо менять search анализатор.

Спасибо.

---

<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:** [May 25, 2017, 2:44pm UTC](https://discuss.elastic.co/t/topic/87136/2 "2017-05-25T14:44:12Z")

</div>

А если пользователь ищет `клен-дуб`, то поиск должен вернуть `клен и где то-там дальше в конце поля дуб`?

---

<div class="post-metadata">

**Author:** ![klara](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/klara/32/18440_2.png) [@klara](https://discuss.elastic.co/u/klara)\
**Post date:** [May 25, 2017, 3:00pm UTC](https://discuss.elastic.co/t/topic/87136/3 "2017-05-25T15:00:54Z")

</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:** [May 26, 2017, 2:56pm UTC](https://discuss.elastic.co/t/topic/87136/4 "2017-05-26T14:56:10Z")

</div>

Думаю, проще всего будет заменить все `-` на `_` с помощью [char\_filter](https://www.elastic.co/guide/en/elasticsearch/reference/5.4/analysis-mapping-charfilter.html).

---

<div class="post-metadata">

**Author:** ![klara](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/klara/32/18440_2.png) [@klara](https://discuss.elastic.co/u/klara)\
**Post date:** [May 26, 2017, 3:42pm UTC](https://discuss.elastic.co/t/topic/87136/5 "2017-05-26T15:42:15Z")

</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:** [May 26, 2017, 9:13pm UTC](https://discuss.elastic.co/t/topic/87136/6 "2017-05-26T21:13:51Z")

</div>

Ну, как-то вот так

```auto
DELETE test
PUT test
{
  "settings": {
    "analysis": {
      "char_filter": {
        "replace_dash_char_filter": {
          "type": "mapping",
          "mappings": [
            "- => _"
          ]
        }
      },
      "analyzer": {
        "my_analyzer": {
          "char_filter": [
            "replace_dash_char_filter"
          ],
          "tokenizer": "standard",
          "filter": [
            "lowercase"
          ]
        }
      }
    }
  },
  "mappings": {
    "doc": {
      "properties": {
        "message": {
          "type": "text",
          "analyzer": "my_analyzer"
        }
      }
    }
  }
}

PUT test/doc/_bulk?refresh
{"index":{"_id":1}}
{"message" : "клен-дуб и грибы"}
{"index":{"_id":2}}
{"message" : "Клен или дуб, вот в чем вопрос"}
{"index":{"_id":3}}
{"message" : "Стоит дуб-дубом, ничего не отвечает"}
{"index":{"_id":4}}
{"message" : "Дуб-дуб это вам не клен и дуб"}

GET test/doc/_search
{
  "query": {
    "match": {
      "message": "клен-дуб"
    }
  }
}

GET test/doc/_search
{
  "query": {
    "match": {
      "message": "дуб-дуб"
    }
  }
}

GET test/doc/_search
{
  "query": {
    "match": {
      "message": "клен дуб"
    }
  }
}

```

---

<div class="post-metadata">

**Author:** ![klara](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/klara/32/18440_2.png) [@klara](https://discuss.elastic.co/u/klara)\
**Post date:** [May 27, 2017, 10:08am UTC](https://discuss.elastic.co/t/topic/87136/7 "2017-05-27T10:08:06Z")

</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:** [May 30, 2017, 1:30pm UTC](https://discuss.elastic.co/t/topic/87136/8 "2017-05-30T13:30:38Z")

</div>

> Реализовать можно и просто двумя запросами конечно...

Да, я думаю проще одним запросом но по двум полям:

```auto
DELETE test
PUT test
{
  "settings": {
    "analysis": {
      "char_filter": {
        "replace_dash_char_filter": {
          "type": "mapping",
          "mappings": [
            "- => _"
          ]
        }
      },
      "analyzer": {
        "my_analyzer": {
          "char_filter": [
            "replace_dash_char_filter"
          ],
          "tokenizer": "standard",
          "filter": [
            "lowercase"
          ]
        }
      }
    }
  },
  "mappings": {
    "doc": {
      "properties": {
        "message": {
          "type": "text",
          "analyzer": "my_analyzer",
          "fields": {
            "standard": {
              "type": "text",
              "search_analyzer": "my_analyzer", 
              "analyzer": "standard"
            }
          }
        }
      }
    }
  }
}

PUT test/doc/_bulk?refresh
{"index":{"_id":1}}
{"message" : "клен-дуб и грибы"}
{"index":{"_id":2}}
{"message" : "Клен или дуб, вот в чем вопрос"}
{"index":{"_id":3}}
{"message" : "Стоит дуб-дубом, ничего не отвечает"}
{"index":{"_id":4}}
{"message" : "Дуб-дуб это вам не клен и дуб"}

GET test/doc/_search
{
  "query": {
    "multi_match": {
      "query": "клен-дуб",
      "fields": ["message^2", "message.standard"]
    }
  }
}

GET test/doc/_search?explain
{
  "query": {
    "multi_match": {
      "query": "клен",
      "fields": ["message^2", "message.standard"]
    }
  }
}

```

---

<div class="post-metadata">

**Author:** ![klara](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/klara/32/18440_2.png) [@klara](https://discuss.elastic.co/u/klara)\
**Post date:** [May 30, 2017, 5:26pm UTC](https://discuss.elastic.co/t/topic/87136/9 "2017-05-30T17:26:23Z")

</div>

Гениально!

Огромное спасибо)

---

<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:** [June 27, 2017, 5:26pm UTC](https://discuss.elastic.co/t/topic/87136/10 "2017-06-27T17:26:55Z")

</div>

Closed on June 27, 2017, 5:26pm UTC

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