# Помогите составить запрос с исключениями

**URL:** <https://discuss.elastic.co/t/topic/77469>\
**Category:** Вопросы на русском языке\
**Created:** [March 6, 2017, 10:15am UTC](https://discuss.elastic.co/t/topic/77469 "2017-03-06T10:15:09Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![pablissimo77](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/pablissimo77/32/108804_2.png) [@pablissimo77](https://discuss.elastic.co/u/pablissimo77)\
**Post date:** [March 6, 2017, 10:15am UTC](https://discuss.elastic.co/t/topic/77469/1 "2017-03-06T10:15:09Z")

</div>

Здравствуйте! Изучаю ElasticSearch несколько месяцев, создал индекс с подобным типом документа:

```
"mappings": {
    "news": {
      "properties" : {
        "title" : {"type" : "text", "fields" : {"russian" : {"type" : "text", "analyzer": "russian"}, "ukrainian" : {"type" : "text", "analyzer": "ukrainian"}}}
      }
     }
}

```

Документы в индекс поступают как на русском, так и на украинском языке. Для украинского аналайзера инсталлировал плагин.  
Допустим есть такие фразы:  
1: "Тарас Шевченко автор Кобзаря"  
2: "Андрей Шевченко тренер сборной Украины по футболу"  
3: "Тарас Шевченко и Адрей Шевченко - знаменитые украинцы"  
4: "Шевченко завтра проведет прессконференцию"

Так вот, как мне написать запрос, который бы исключал определенные сочетания ключевых фраз для поиска, например, я ищу документы только о Андрее Шевченко и о Шевченко без упоминания имени (2,3,4)  
Запрос

```
{
"query": {
    "bool": {
        "should": [
                     {"match_phrase":{"title.russian" :"Шевченко"}},
                     {"match_phrase":{"title.ukrainian" :"Шевченко"}}
               ],
          "minimum_should_match":1 
     }
 }
}

```

выдаст мне все документы.  
Как исключить Тараса Шевченко?) Когда я использую в bool запросе must\_not я теряю фразу, где они упоминаются оба...  
Надеюсь не путано объяснил 🙂

---

<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:** [March 6, 2017, 6:20pm UTC](https://discuss.elastic.co/t/topic/77469/2 "2017-03-06T18:20:49Z")

</div>

А если поместить только Тараса в `must_not`? Если честно, я не понимаю. что вы пытаетесь добиться. Вы не могли бы описать проблему, которую вы пытаетесь решить?

---

<div class="post-metadata">

**Author:** ![pablissimo77](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/pablissimo77/32/108804_2.png) [@pablissimo77](https://discuss.elastic.co/u/pablissimo77)\
**Post date:** [March 7, 2017, 7:02am UTC](https://discuss.elastic.co/t/topic/77469/3 "2017-03-07T07:02:46Z")

</div>

Если я сделаю так

```
{
"query": {
    "bool": {
        "must_not": [
          {"match_phrase":{"title.russian" :"Тарас"}},
          {"match_phrase":{"title.ukrainian" :"Тарас"}}
        ], 
        "should": [
                     {"match_phrase":{"title.russian" :"Шевченко"}},
                     {"match_phrase":{"title.ukrainian" :"Шевченко"}}
        ], "minimum_should_match":1 
    }
}
}

```

То запрос мне выдаст 2 и 4 документ, но я потеряю 3, а мне он нужен, так как там есть Андрей Шевченко )

Моя проблема в том, что мне нужно найти все документы, где есть Шевченко, но определенные словосочетания нужно исключить (Тарас Шевченко, музей Шевченко и т.п.), а определенные (Андрей Шевченко или просто Шевченко) должны находится запросом. Если я буду делать must\_not на "Тарас" или "Тарас Шевченко" я буду терять документы, в которых они встречаются оба... Т.е. мне нужно что-то типа should\_not ))

---

<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:** [March 7, 2017, 7:11am UTC](https://discuss.elastic.co/t/topic/77469/4 "2017-03-07T07:11:47Z")

</div>

> [@pablissimo77](#):
>
> но определенные словосочетания нужно исключить (Тарас Шевченко, музей Шевченко и т.п.),

А эти словосочетания более-менее постоянные, или они меняются при каждом запросе?

---

<div class="post-metadata">

**Author:** ![pablissimo77](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/pablissimo77/32/108804_2.png) [@pablissimo77](https://discuss.elastic.co/u/pablissimo77)\
**Post date:** [March 7, 2017, 7:16am UTC](https://discuss.elastic.co/t/topic/77469/5 "2017-03-07T07:16:03Z")

</div>

Более-менее постоянные  
Т.е. я могу для ключевой фразы "Шевченко" (иногда это будет фраза, а не слово, просто я привел Шевченко для примера) подобрать словосочетания, которые мне нужно исключить.

---

<div class="post-metadata">

**Author:** ![pablissimo77](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/pablissimo77/32/108804_2.png) [@pablissimo77](https://discuss.elastic.co/u/pablissimo77)\
**Post date:** [March 7, 2017, 8:22am UTC](https://discuss.elastic.co/t/topic/77469/6 "2017-03-07T08:22:25Z")

</div>

Корректно ли будет использовать такую конструкцию?

```
{
"min_score":0,
"query": {
    "bool":{
     "should": [
                     {"match_phrase":{"title.russian":{ "query" :"Шевченко", "boost":1}}},
                     {"match_phrase":{"title.russian":{ "query" :"Андрей Шевченко", "boost":1}}},
                     {"match_phrase":{"title.russian":{ "query" :"Тарас Шевченко", "boost":-1}}},
                     {"match_phrase":{"title.russian":{ "query" :"университет Шевченко", "boost":-1}}},
                     {"match_phrase":{"title.ukrainian":{ "query" :"Шевченко", "boost":1}}},
                     {"match_phrase":{"title.ukrainian":{ "query" :"Андрей Шевченко", "boost":1}}},
                     {"match_phrase":{"title.ukrainian":{ "query" :"Тарас Шевченко", "boost":-1}}},
                     {"match_phrase":{"title.ukrainian":{ "query" :"университет Шевченко", "boost":-1}}}
      ], "minimum_should_match":1 
    }
  }
}

```

Такой запрос выдает нужные документы 2,3,4 но я не уверен, что это правильно будет работать на других документах )

---

<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:** [March 8, 2017, 8:20pm UTC](https://discuss.elastic.co/t/topic/77469/7 "2017-03-08T20:20:00Z")

</div>

А вы можете подобрать **все** словосочетания, которые вы хотели бы исключить из индекса при индексации?

---

<div class="post-metadata">

**Author:** ![pablissimo77](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/pablissimo77/32/108804_2.png) [@pablissimo77](https://discuss.elastic.co/u/pablissimo77)\
**Post date:** [March 8, 2017, 9:09pm UTC](https://discuss.elastic.co/t/topic/77469/8 "2017-03-08T21:09:53Z")

</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:** [March 8, 2017, 9:21pm UTC](https://discuss.elastic.co/t/topic/77469/9 "2017-03-08T21:21:37Z")

</div>

Тогда хорошего решения, наверное, нет.

---

<div class="post-metadata">

**Author:** ![pablissimo77](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/pablissimo77/32/108804_2.png) [@pablissimo77](https://discuss.elastic.co/u/pablissimo77)\
**Post date:** [March 8, 2017, 9:46pm UTC](https://discuss.elastic.co/t/topic/77469/10 "2017-03-08T21:46:51Z")

</div>

Ясно. Спасибо большое за ответы. Пока буду пользоваться вариантом с положительным и отрицательным boost

---

<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:** [April 5, 2017, 9:47pm UTC](https://discuss.elastic.co/t/topic/77469/11 "2017-04-05T21:47:16Z")

</div>

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