Допустим вы хотите найти документы где FIELD1 = TEXT1 и FIELD2 = TEXT2. Именно для такого случая и подойдёт объединение запросов.

Bool Query

Запрос типа bool - это запрос, который сопоставляет документы, соответствующие логическим комбинациям (true или false) других запросов. Вы можете создавать комбинации из одного или нескольких запросов, включив их в одно или несколько из этих предложений.

Всего 4 вида bool:

  • must
  • must_not
  • filter
  • shuld

Must

Must требует, чтобы все, что находится в условии совпадало. Это почти как оператор and. Запросы в предложении must должны совпадать в возвращаемых документах.

GET INDEX/_search
{ 
"query": {
  "bool": {
    "must": [
	  {
        "match": {
          "FIELD1": "TEXT1"
	    }
      },
      {
        "match": {
          "FIELD2": "TEXT2"
	    }
      }
	]
  }
}

С этим типом запроса Elasticsearch будет искать по двум полям. Оба запроса на совпадение должны быть удовлетворены, чтобы документ был возвращен как попадание. Это означает, что наличие большего количества запросов в предложении must повысит precision вашего запроса. Score будет рассчитана по обоим пунктам, а затем суммирована.

Must_not

Собственно это бобратная от must. Must_not используется для исключения информации. Слово не должно появляться в соответствующих документах. Так как термин не появляется в документах, все возвращенные документы имеют score 0. Фактически, алгоритм оценки вообще пропускается.

GET INDEX/_search
{ 
"query": {
  "bool": {
    "must": 
	  {
        "match": {
          "FIELD1": "TEXT1"
	    }
      },
	"must_not": [ 
      {
        "match": {
          "FIELD2": "TEXT2"
	    }
      }
	]  
  }
}

Should

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

Для примера допустим вы ищиите FIELD1 со значением TEXT1 и FIELD2 со значнием TEXT2 применяя should. В результате первыми в списке будут выводится документы, которые имеют значение TEXT2 в поле FIELD2.

Should не исключает документы из вывода, он просто их сортирует.

GET INDEX/_search
{ 
"query": {
  "bool": {
    "must": 
	  {
        "match": {
          "FIELD1": "TEXT1"
	    }
      },
	"should": [ 
      {
        "match": {
          "FIELD2": "TEXT2"
	    }
      }
	]  
  }
}

Filter

Score для filter не рассчитывается. Применение filter это по сути вопрос на ответ ДА или НЕТ. Например вы задаёте вопрос: Дата публикации входит в интервал дней? Если ответ ДА, то документ будет выведен в результатах запроса.

GET INDEX/_search
{ 
"query": {
  "bool": {
    "must": {
      "match": {
        "FIELD1": "TEXT1"
	  }
    },
	"filter": {
      "range": {
		"DATE": {
          "lt": "2020-01-01"
		}	
	  }
    } 
  }
}
GET INDEX/_search
{
  "query": {
    "bool": {
      "must": [
        { "match": {
          "FIELD1": "TEXT1"
        }}
      ],
      "filter": [
        {"range": {
          "DATE": {
            "gte": "2017-12-01",
            "lt": "2018-01-01"
          }
        }}
      ]
    }
  }
}		  

Query и Filter

Если вы хотите узнать, насколько хорошо документ соответствует запросу, используйте обычный query. Если вас не интересует _score и вы хотите знать, соответствует ли документ запросу, используйте filter.

Итоговая таблица

Тип запроса Влияет на hits Влияет на _score Фильтрует документы
must + + -
must_not + - +
should - + -
filter + - +

.

Математические операции

В Elasticsearch есть удобный способ выразить диапазоны дат с помощью математических вычислений. Пример, который вы видите здесь, собирает данные за 10 лет.

GET INDEX/_search
{
  "query": {
    "bool": {
      "must": [
        { "match": {
          "FIELD1": "TEXT1"
        }}
      ],
      "filter": [
        {"range": {
          "DATE": {
            "gte": "now-10y"
          }
        }}
      ]
    }
  }
}

Таблица математических операций с датами (Date Math Expressions)

Абревиатура Расшифровка Операции
M месяцы  
w недели  
d дни now/d+1d
h или H часы now-1H
m минуты now-1H+30m
s секунды  
y годы 2018-01-01||+1y (2019-01-01)

.

Keyword

Еще один вариант аналогичный match_phrase для query. Т.е запрос с keyword ищет полностью всю фразу целиком, а не каждое слово отдельно.

GET INDEX/_search
{
  "query": {
    "bool": {
      "must": [
        { "match": {
          "FIELD1": "TEXT1"
        }}
      ],
      "filter": [
        {"match": {
          "FIELD2.keyword": "TEXT2 in TEXT3"
        }
        }
      ]
    }
  }
}

Сортировка вывода (order)

Для сортировки ответа на запрос модно использовать order, которое принимает значения DESC или ASC. Т.е сортирует поля по возрастанию или убыванию. При этом сортировка по _score не происходит (_score равно 0).

Также при использовании order в ответе на запрос появляется поле sort (“sort” : [“Text my text”]).

GET INDEX/_search
{
  "query": {
    "bool": {
      "must": [
        { "match": {
          "FIELD1": "TEXT1"
        }}
      ]
    }
  },
  "sort": [
    {
      "FIELD1.keyword": {
        "order": "desc"
      }
    }
  ]
}

From

По умолчанию elasticsearch показывает только по 10 документов в ответе на запрос. Для того чтобы смотреть другие документы можно восспользоваться from, которому в цифровом формате передаём значение с какого документа начать просмотр. Работает как pagination на веб сайтах.

GET INDEX/_search
{
  "from": 20, 
  "query": {
    "bool": {
      "must": [
        { "match": {
          "FIELD1": "TEXT1"
        }}
      ]
    }
  },
  "sort": [
    {
      "FIELD1.keyword": {
        "order": "desc"
      }
    }
  ]
}

Также если хочется вывести больше 10 документов можно восспользоваться size.

GET INDEX/_search
{
  "size": 20, 
  "query": {
    "bool": {
      "must": [
        { "match": {
          "FIELD1": "TEXT1"
        }}
      ]
    }
  },
  "sort": [
    {
      "FIELD1.keyword": {
        "order": "desc"
      }
    }
  ]
}

Выделение найденных слов (Highlight)

Бывает что нужно найти те слова, которые вы задавали в поиске и что-то с ними сделать. Например задать им другой html тэг. Вэтом поможет highlight.

GET INDEX/_search
{
  "query": {
    "bool": {
      "must": [
        { "match": {
          "FIELD1": "TEXT1"
        }}
      ]
    }
  }
  , "highlight": {
    "fields": {
      "FIELD1": {}
    }
    , "pre_tags": ["<a>"]
    , "post_tags": ["</a>"]
  }
}

В итоге получим отдельное поле в выводе со значением:

"highlight" : {
  "FIELD1" : [
    "dsadsad n <a>TEXT1</a>: dsadadasd <a>TEXT1</a>"
  ]
}