КатегорииElasticsearchУроки

Elasticsearch — Урок 6.5 Поиск по нескольким полям

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

Чтобы расширить поиск, мы можем попробовать искать в description и product_name. Документ, содержащий оба слова показан здесь:

{
    "product_name": "Мужская качественная кожаная куртка",
    "description": "Лучший выбор. Всесезонная кожаная куртка",
    "unit_price": 79.99,
    "reviews": 250,
    "release_date": "2016-08-16"
}

Оценка на основе одного поля довольно проста, оценка на основе нескольких полей становится несколько сложней. Лучшим решением будет использовать multi_match для поиска по полям product_name и description:

 #Multi Match
 GET example6/_search
 {
   "query": {
     "multi_match": {
       "query": "всесезонная куртка",
       "fields": [
         "product_name",
         "description"
       ],
       "type": "best_fields"
     }
   }
 }

По умолчанию запрос multi_match выполняется в режиме best_fields. Используется оценка лучше всего совпадающего поля. Мы также можем использовать, tie_breaker чтобы суммировать оценки из других полей, как показано ниже:

#Multi Match
POST example6/_search
{
   "query": {
     "multi_match": {
       "query": "всесезонная куртка",
       "fields": [
         "product_name",
         "description"
       ],
       "tie_breaker": 0.2
     }
   }
 }

Оценки из других полей умножаются 0.2 и добавляются к лучшему совпадающему полю. Multi-match внутренне переводится в dis_max запрос. В отличие от bool запроса, который суммирует все оценки из всех запросов, dis_max запрос возвращает оценку наилучшего совпадающего запроса:

#Dis max Query
POST example6/_search
{
   "query": {
     "dis_max": {
       "queries": [
         {
           "match": {
             "product_name": "всесезонная куртка"
           }
         },
         {
           "match": {
             "description": "всесезонная куртка"
           }
         }
       ]
     }
   }
 }

Multi-match также предоставляет некоторые полезные настройки, чтобы увеличить оценку для отдельных полей. Если совпадение product_name более важно, чем description, мы можем увеличить важность product_name используя символ каретки (^), как показано ниже:

POST example6/_search
 {
   "query": {
     "multi_match": {
       "query": "всесезонная куртка",
       "fields": [
         "product_name^2",
         "description"
       ]
     }
   }
 }

В зависимости от того, как вы хотите, чтобы документы были оценены, multi_match поддерживаются три типа запроса. Эти типы отличаются тем, как используются оценки из разных полей для расчета окончательной оценки каждого документа. В следующих разделах мы попробуем запустить все три типа на примере одного запроса и посмотрим как изменяется оценка.

best_fields

best_fields являются типом по умолчанию, и возвращается результат наилучшего совпадающего поля. Например, если вы в поисках слова куртка в product_name и description полях, multi_match запрос выглядит следующим образом:

#Multi Match (Best Fields)
POST example6/_search
 {
   "query": {
     "multi_match": {
       "query": "куртка",
       "fields": [
         "product_name",
         "description"
       ],
       "type": "best_fields",
       "analyzer" : "russian"
     }
   }
 }

По умолчанию термин запроса анализируется и разбивается на отдельные термины на основе анализатора полей. Например, мы спрашиваем о мужская куртка. Используя стандартный анализатор, запрос разбивается на мужская и куртка. При использовании русского анализатора запрос будет разбит на мужск и куртк. Указав анализатор, мы просим Elasticsearch использовать тот же анализатор для всех полей, независимо от их сопоставлений.

Большинство совпадающих полей (most_fields)

Multi_match запрос, при выполнении с типом most_fields суммирует баллы всех полей. Давайте попробуем тот же запрос, но зададим тип most_fields:

#Multi Match (Most Fields)
POST example6/_search
 {
   "query": {
     "multi_match": {
       "query": "куртка",
       "fields": [
         "product_name",
         "description"
       ],
       "type": "most_fields",
       "analyzer" : "russian"
     }
   }
 }

Результат:

{
   ....
   "hits": {
    "total": 3,
    "max_score": 0.5753642,
    "hits": [
      {
        "_index": "example6",
        "_type": "product",
        "_id": "1",
        "_score": 0.5753642,
        "_source": {
          "product_name": "Мужская качественная кожаная куртка",
          "description": "Лучший выбор. Всесезонная кожаная куртка",
          "unit_price": 79.99,
          "reviews": 250,
          "release_date": "2016-08-16"
        }
      },
      {
        "_index": "example6",
        "_type": "product",
        "_id": "2",
        "_score": 0.2876821,
        "_source": {
          "product_name": "Мужская водостойкая куртка",
          "description": "Обеспечивает комфорт во время езды на велосипеде",
          "unit_price": 69.99,
          "reviews": 5,
          "release_date": "2017-03-02"
        }
      },
      {
        "_index": "example6",
        "_type": "product",
        "_id": "3",
        "_score": 0.2876821,
        "_source": {
          "product_name": "Куртка женская шерстяная",
          "description": "Согреет вас зимой",
          "unit_price": 59.99,
          "reviews": 10,
          "release_date": "2018-01-15"
        }
      }
    ]
  }
 }

Соединение полей (cross_fields)

Предыдущие типы выполняют запрос в разных полях и объединяют баллы для получения окончательного результата. Данный тип идет своей дорогой, а именно объединяет поля, как если бы они были одной большой строкой и уже следом происходит поиск и оценка:

#Multi Match (Cross Fields)
POST example6/_search
 {
   "query": {
     "multi_match": {
       "query": "куртка",
       "fields": [
         "product_name",
         "description"
       ],
       "type": "cross_fields",
       "analyzer" : "russian"
     }
   }
 }
Так же в нашем распоряжение есть типы phrase — поиск фразы и phrase_prefix — поиск фразы с не точным окончанием. Если интересно поэкспериментируйте и с ними.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *