# Поиск по нескольким полям с разными типами

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

<div class="post-metadata">

**Author:** ![symbios-zi](https://avatars.discourse-cdn.com/v4/letter/s/f475e1/32.png) [@symbios-zi](https://discuss.elastic.co/u/symbios-zi)\
**Post date:** [May 5, 2017, 10:31am UTC](https://discuss.elastic.co/t/topic/84695/1 "2017-05-05T10:31:11Z")

</div>

Здравствуйте.

Как правильно организовать поиск по разным полям?

У меня есть индекс  
orders

- order\_number (long)
- domain\_id (long)
- first\_name (string)
- last\_name (string)

1.К примеру если поисковый запрос "18000" то в первую очередь нужно точное совпадение по полю order\_number  
2. Если поисковый запрос "Артемов Артем", то ищем по полям first\_name, last\_name применяя fuzzy  
3. Если выбран фильтр по домену (domain\_id =3) применить его тоже в этом запросе, отфильтровав все записи по domain\_id =3

Возможно ли объединение match и multi\_match?

Возможно я неверно понимаю, и правильно иначе?

---

<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 5, 2017, 7:02pm UTC](https://discuss.elastic.co/t/topic/84695/2 "2017-05-05T19:02:24Z")

</div>

Я бы преобразовал 1 и 2 в `match` и добавил их как `should` элементы в `bool` с подходящим `boost`-ом. А 3 я бы добавил как `filter` в тот-же самый `bool`. Можно это все как `multi_match` выразить, но там возможностей меньше, и если вы парсите запросы, что бы понять что в них находится, то уж лучше сразу формулировать запрос `bool`.

---

<div class="post-metadata">

**Author:** ![symbios-zi](https://avatars.discourse-cdn.com/v4/letter/s/f475e1/32.png) [@symbios-zi](https://discuss.elastic.co/u/symbios-zi)\
**Post date:** [May 6, 2017, 11:51am UTC](https://discuss.elastic.co/t/topic/84695/3 "2017-05-06T11:51:37Z")

</div>

Несколько раз прочел документацию, и не смог понять до конца как работают must и should.

Правильно ли я понимаю что must (обязан) означает точное совпадение?  
Тогда как работает should (следует)?

Еще один вопрос:  
у меня все запросы приходят через одно поле поиска где может быть как имя, фамилия так и номер заказа. а еще в поиске может быть индекс (423040) что может совпасть с номером заказа. Видимо тут нужно сделать приоритет номера заказа в таком случае?

---

<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 6, 2017, 1:37pm UTC](https://discuss.elastic.co/t/topic/84695/4 "2017-05-06T13:37:52Z")

</div>

> [@symbios-zi](#):
>
> Несколько раз прочел документацию, и не смог понять до конца как работают must и should.

А вы поэкспериментируйте. Поставьте elasticsearch и kibana, проиндексируйте несколько документов и посмотрите, что возвращается. Надо только обратить внимание на то, что поведение `should` зависит от параметра `minimum_should_match`. В свою очередь значение по умолчанию для `minimum_should_match` зависит от наличия `must` и `must_not` в запросе. Если `must` и `must_not` присутствуют, то `minimum_should_match` равен 0, если нет - то 1. Когда `minimum_should_match` равен 1, то по крайней мере один `should` должен совпадать для того, чтобы документ попал в результат, то есть `should` работает как "или". Если `minimum_should_match` равен 0, то `should` на выборку результатов не влияет, но совпадения увеличивают `_score`, и если вы сортирует по `_score`, то соответсвенно порядок документов в результате. Когда `minimum_should_match` равен 2, то как минимум два `should` должны совпадать, и как в случае с 0 и 1, если больше `should` совпадает, то `_score` увеличивается.

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

... либо добавить 1000000 ко всем номерам заказов, чтобы их формат с индексами не мог совпасть.

---

<div class="post-metadata">

**Author:** ![symbios-zi](https://avatars.discourse-cdn.com/v4/letter/s/f475e1/32.png) [@symbios-zi](https://discuss.elastic.co/u/symbios-zi)\
**Post date:** [May 6, 2017, 1:40pm UTC](https://discuss.elastic.co/t/topic/84695/5 "2017-05-06T13:40:31Z")

</div>

нумерацию уже изменить не могу. Решил попробовать внедрить префиксы поиска:  
О18000  
И423042

и для них уже делать точные совпадения

---

<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 6, 2017, 1:45pm UTC](https://discuss.elastic.co/t/topic/84695/6 "2017-05-06T13:45:04Z")

</div>

Я думаю, что в этом случае надо искать по заказам с большим приоритетом. Заказ с определенным номером всегда один, а покупателей с одним и тем же индексом - может быть много. Так что для пользователя, которому нужен индекс, пропустить первую запись не так уж сложно.

---

<div class="post-metadata">

**Author:** ![symbios-zi](https://avatars.discourse-cdn.com/v4/letter/s/f475e1/32.png) [@symbios-zi](https://discuss.elastic.co/u/symbios-zi)\
**Post date:** [May 6, 2017, 2:43pm UTC](https://discuss.elastic.co/t/topic/84695/7 "2017-05-06T14:43:09Z")

</div>

согласен. Обработчики заказов подтвердили ваши слова.

---

<div class="post-metadata">

**Author:** ![symbios-zi](https://avatars.discourse-cdn.com/v4/letter/s/f475e1/32.png) [@symbios-zi](https://discuss.elastic.co/u/symbios-zi)\
**Post date:** [May 7, 2017, 10:48am UTC](https://discuss.elastic.co/t/topic/84695/8 "2017-05-07T10:48:13Z")

</div>

Игорь, поставил кибану и попробовал различные запросы:

Еще один вопрос:  
Администратор вводит запрос с индексом и именем, и хочет получить результаты по релевантности. Сначала все заказы где такой индекс и имя клиента, потом индекс, и потом только имя. Но такой запрос вообще не выдает ни одного результата. Правильно ли я понимаю что верный вариант разбить строку запроса на текст и число, и подставить уже эти подстроки по полям:

postcode: численная часть  
name: строковая часть

```
пытаюсь такой запрос построить. 

# query string: 111675 артем
GET orders/_search
{
  "query": { 
    "bool": { 
      "should": [
        { "term" : { 
          "order_number" : {
            "boost": 2,
            "value": "111675 артем"
          }} 
        },
        { "term" : { 
          "postcode" : {
            "boost": 1,
            "value": "111675 артем"
          }} 
        },
        { "fuzzy" : { "firstname" : "111675 артем" } },
        { "fuzzy" : { "lastname" : "111675 артем" } }
      ],
      "minimum_should_match" : 1,
      "filter": [ 
        { "term": { "domain_id": 3 }}
      ]
    }
  }
}

```

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

Или же можно как то избежать парсинга и получить такой же результат?

```
# query string: 111675 артем
GET orders/_search
{
  "query": { 
    "bool": { 
      "should": [
        { "term" : { 
          "order_number" : {
            "boost": 2,
            "value": "111675"
          }} 
        },
        { "term" : { 
          "postcode" : {
            "boost": 1,
            "value": "111675"
          }} 
        },
        { "fuzzy" : { "firstname" : "артем" } },
        { "fuzzy" : { "lastname" : "артем" } }
      ],
      "minimum_should_match" : 1,
      "filter": [ 
        { "term": { "domain_id": 3 }}
      ]
    }
  }
}
```

---

<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 7, 2017, 6:26pm UTC](https://discuss.elastic.co/t/topic/84695/9 "2017-05-07T18:26:49Z")

</div>

Это происходит потому, что запросы `term` и `fuzzy` не [анализируют](https://www.elastic.co/guide/en/elasticsearch/guide/master/mapping-analysis.html) запрос.

---

<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 4, 2017, 6:33pm UTC](https://discuss.elastic.co/t/topic/84695/10 "2017-06-04T18:33:24Z")

</div>

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