# Сортировка результатов по максимальному числу совпадащих фильтров

**URL:** <https://discuss.elastic.co/t/topic/275406>\
**Category:** Вопросы на русском языке\
**Created:** [June 9, 2021, 8:52am UTC](https://discuss.elastic.co/t/topic/275406 "2021-06-09T08:52:19Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![itmariacchi](https://avatars.discourse-cdn.com/v4/letter/i/ce7236/32.png) [@itmariacchi](https://discuss.elastic.co/u/itmariacchi)\
**Post date:** [June 9, 2021, 8:52am UTC](https://discuss.elastic.co/t/topic/275406/1 "2021-06-09T08:52:19Z")

</div>

Здравствуйте!  
Есть индекс специалистов, у специалистов есть, например, ключевые навыки (множественное поле). Пользователь в фильтре выбирает ключевые навыки - например, PHP, JS, Java. Так вот специалисты, у которых например, совпадают три навыка, должны выдаваться в списке выше, чем те, у кого совпадает два.

```auto
{"query":{"nested":{"path":"key_skills","query":{"bool":{"should":[{"term":{"key_skills.slug":"kn-zr-1"}},{"term":{"key_skills.slug":"key-skill-01"}}],"minimum_should_match":1}}}},"from":0,"size":10000,"_source":["index","key_skills"],"sort":"_score"}

```

В теории, по-умолчанию эластик так и должен работать. Когда я провожу тесты и заполняю поле key\_skills предопределенным набором значений: [ks1] или [ks1, ks2] или [ks1, ks2, ks3] - то все работает. Однако, когда в поле реальные данные из базы - сортировка не верная.

Более того, я проводил эксперимент на одном специалисте и происходит мистика. У него три ключевых скила key-skill-1, key-skill-01, key-skill-20.

Когда я делаю запрос с одним фильтром "key\_skills.slug":"key-skill-01", получаю оценку 10.14

```auto
{"query":{"bool":{"must":[{"nested":{"path":"key_skills","query":{"bool":{"should":[{"term":{"key_skills.slug":"key-skill-01"}}],"minimum_should_match":1}}}},{"term":{"index":"219"}}]}},"from":0,"size":10000,"_source":["index","key_skills"],"sort":"_score"}

```

Если же я делаю запрос с двумя значениями в фильтре, оценка понижается до 9.7

```auto
{"query":{"bool":{"must":[{"nested":{"path":"key_skills","query":{"bool":{"should":[{"term":{"key_skills.slug":"key-skill-01"}},{"term":{"key_skills.slug":"key-skill-1"}}],"minimum_should_match":1}}}},{"term":{"index":"219"}}]}},"from":0,"size":10000,"_source":["index","key_skills"],"sort":"_score"}

```

---

<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:** [June 9, 2021, 7:00pm UTC](https://discuss.elastic.co/t/topic/275406/2 "2021-06-09T19:00:17Z")

</div>

> [@itmariacchi](#):
>
> и происходит мистика

Как сказал, старик Кларк: "Любая достаточно развитая технология неотличима от магии." 🙂

> [@itmariacchi](#):
>
> В теории, по-умолчанию эластик так и должен работать.

В теории, [все немного сложнее](https://www.elastic.co/blog/practical-bm25-part-2-the-bm25-algorithm-and-its-variables). Elasticsearch, по-умолчанию, пытается не только найти большинство совпадений, но и оценить, какие совпадения более ценные, предпочитая более редкие термины, терминам, которые встречаются в большом количестве записей.

То что вы хотите, можно добиться либо настроив [scripted similarity](https://www.elastic.co/guide/en/elasticsearch/reference/current/index-modules-similarity.html#scripted_similarity), которая возвращает только `doc.freq`, либо завернуть все запросы в terms в [constant\_score](https://www.elastic.co/guide/en/elasticsearch/reference/7.13/query-dsl-constant-score-query.html).

```auto
{
  "query": {
    "nested": {
      "path": "key_skills",
      "query": {
        "bool": {
          "should": [
            {
              "constant_score": {
                "filter": {
                  "term": {
                    "key_skills.slug": "kn-zr-1"
                  }
                }
              }
            },
            {
              "constant_score": {
                "filter": {
                  "term": {
                    "key_skills.slug": "key-skill-01"
                  }
                }
              }
            }
          ],
          "minimum_should_match": 1
        }
      }
    }
  },
  "from": 0,
  "size": 10000,
  "_source": [
    "index",
    "key_skills"
  ],
  "sort": "_score"
}

```

---

<div class="post-metadata">

**Author:** ![itmariacchi](https://avatars.discourse-cdn.com/v4/letter/i/ce7236/32.png) [@itmariacchi](https://discuss.elastic.co/u/itmariacchi)\
**Post date:** [June 10, 2021, 6:55am UTC](https://discuss.elastic.co/t/topic/275406/3 "2021-06-10T06:55:34Z")

</div>

Да вот никак эта магия контролю не поддается только 🙂 Применил constant\_score, как вашем примере и почему-то всем документам проставилась оценка - 1, вне зависимости от того, сколько значений совпало. Видимо, придется смотреть в сторону scripted similarity

---

<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:** [June 10, 2021, 2:35pm UTC](https://discuss.elastic.co/t/topic/275406/4 "2021-06-10T14:35:33Z")

</div>

> [@itmariacchi](#):
>
> эта магия контролю не поддается только

Ну это на волшебника еще немного поучиться надо 🙂 Вы `constant_score` вокруг всего запроса поставили, или завернули каждый отдельный запрос `term` в `constant_score`, как показано в моем примере?

---

<div class="post-metadata">

**Author:** ![itmariacchi](https://avatars.discourse-cdn.com/v4/letter/i/ce7236/32.png) [@itmariacchi](https://discuss.elastic.co/u/itmariacchi)\
**Post date:** [June 11, 2021, 11:17am UTC](https://discuss.elastic.co/t/topic/275406/5 "2021-06-11T11:17:22Z")

</div>

Сделал как на вашем примере, но работать не хотело. Но в общем я вопрос решил, дело в nested поле. Я делал запрос nested внутри него несколько should, внутри каждого по одному term. А нужно сделать несколько should, внутри каждого один nested с одним term внутри.

```auto
{"query":{"bool":{"should":[{"nested":{"path":"key_skills","query":{"term":{"key_skills.slug":"key-skill-01"}}}},{"nested":{"path":"key_skills","query":{"term":{"key_skills.slug":"key-skill-02"}}}},{"nested":{"path":"key_skills","query":{"term":{"key_skills.slug":"key-skill-0389439"}}}},{"nested":{"path":"key_skills","query":{"term":{"key_skills.slug":"google-analytics"}}}}],"minimum_should_match":1}},"from":0,"size":10000,"_source":["index","key_skills"]}

```

---

<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:** [July 9, 2021, 11:18am UTC](https://discuss.elastic.co/t/topic/275406/6 "2021-07-09T11:18:13Z")

</div>

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