Elasticsearch bool query объединяется с OR
В настоящее время я пытаюсь перенести приложение solr на elasticsearch.
У меня есть этот запрос lucene
((
name:(+foo +bar)
OR info:(+foo +bar)
)) AND state:(1) AND (has_image:(0) OR has_image:(1)^100)
Насколько я понимаю, это комбинация предложений MUST в сочетании с булевым OR:
"Получить все документы, содержащие (foo AND bar в имени) ИЛИ (foo AND bar в информации). После этого результат фильтра определяется условием state = 1 и форматированием документов, имеющих изображение.
Я пытаюсь использовать bool-запрос с MUST, но я не могу получить логические или необязательные предложения. Вот что я имею:
GET /test/object/_search
{
"from": 0,
"size": 20,
"sort": {
"_score": "desc"
},
"query": {
"bool": {
"must": [
{
"match": {
"name": "foo"
}
},
{
"match": {
"name": "bar"
}
}
],
"must_not": [],
"should": [
{
"match": {
"has_image": {
"query": 1,
"boost": 100
}
}
}
]
}
}
}
Как вы можете видеть, MUST условия для "info" отсутствуют.
У кого-нибудь есть решение?
Большое вам спасибо.
** ОБНОВЛЕНИЕ **
Я обновил свой запрос elasticsearch и избавился от этой функции. Моя базовая проблема все еще существует.
Ответы
Ответ 1
Наконец-то мне удалось создать запрос, который делает именно то, что я хотел:
Отфильтрованный вложенный логический запрос.
Я не уверен, почему это не документировано. Может быть, кто-то здесь может мне сказать?
Вот запрос:
GET /test/object/_search
{
"from": 0,
"size": 20,
"sort": {
"_score": "desc"
},
"query": {
"filtered": {
"filter": {
"bool": {
"must": [
{
"term": {
"state": 1
}
}
]
}
},
"query": {
"bool": {
"should": [
{
"bool": {
"must": [
{
"match": {
"name": "foo"
}
},
{
"match": {
"name": "bar"
}
}
],
"should": [
{
"match": {
"has_image": {
"query": 1,
"boost": 100
}
}
}
]
}
},
{
"bool": {
"must": [
{
"match": {
"info": "foo"
}
},
{
"match": {
"info": "bar"
}
}
],
"should": [
{
"match": {
"has_image": {
"query": 1,
"boost": 100
}
}
}
]
}
}
],
"minimum_should_match": 1
}
}
}
}
}
В псевдо-SQL:
SELECT * FROM /test/object
WHERE
((name=foo AND name=bar) OR (info=foo AND info=bar))
AND state=1
Пожалуйста, имейте в виду, что это зависит от вашего анализа поля поля и отображений, как внутренне обрабатывается имя = foo. Это может варьироваться от нечеткого до строгого поведения.
"minimum_should_match": 1 говорит, что хотя бы одно из утверждений должно быть истинным.
Эти утверждения означают, что всякий раз, когда есть документ в наборе результатов, который содержит has_image: 1, он увеличивается на 100. Это изменяет порядок результатов.
"should": [
{
"match": {
"has_image": {
"query": 1,
"boost": 100
}
}
}
]
Удачи парням:)
Ответ 2
- ИЛИ пишется должно
- И пишется должен
- NOR пишется must_not
Пример:
Вы хотите увидеть все элементы (круглые И (красные ИЛИ синие)):
{
"query": {
"bool": {
"must": [
{
"term": {"shape": "round"}
},
{
"bool": {
"should": [
{"term": {"color": "red"}},
{"term": {"color": "blue"}}
]
}
}
]
}
}
}
Вы также можете делать более сложные версии ИЛИ, например, если вы хотите сопоставить по крайней мере 3 из 5, вы можете указать 5 опций в поле "следует" и установить "минимум_шилда", равный 3.
Спасибо Глену Томпсону и Себастальонсо за то, что они обнаружили, что мое гнездование было не совсем правильным.
Спасибо также Фатмайку за то, что он указал, что термин "соответствует" в ElasticSearch 6.
Ответ 3
Используя вышеизложенное, я получаю
[term] malformed query, expected [END_OBJECT] but found [FIELD_NAME]
Это сработало для меня
Обновлено для Elasticsearch 5.6.4 +
{
"query": {
"bool": {
"must": [
{"term": {"shape": "round"}},
{"bool": {
"should": [
{"term": {"color": "red"}},
{"term": {"color": "blue"}}
]
}}
]
}
}
}
Ответ 4
ElasticSearch определенно ужасен, когда дело доходит до простых запросов, таких как AND, OR или IN. Но вы можете пойти по разумному пути и написать свой запрос как SQL, а затем преобразовать его в синтаксис ElasticSearch с помощью нескольких инструментов (не стесняйтесь редактировать этот список, поскольку оригинальная ссылка кажется мертвой):
Онлайн конвертер SQL в ElasticSearch:
https://www.toolsbuzz.com/query-converter (сейчас не в сети)
https://sqltoelasticsearch.azurewebsites.net
Приложение для Android к ElasticSearch (как странно):
https://play.google.com/store/apps/details?id=com.akshaykumar.sqltoelasticsearch
Ответ 5
Вот как вы можете вкладывать несколько запросов bool в один внешний запрос bool
это с помощью Kibana,
GET my_inedx/my_type/_search
{
"query" : {
"bool": { //bool indicates we are using boolean operator
"must" : [ //must is for **AND**
{
"match" : {
"description" : "some text"
}
},
{
"match" :{
"type" : "some Type"
}
},
{
"bool" : { //here its a nested boolean query
"should" : [ //should is for **OR**
{
"match" : {
//ur query
}
},
{
"match" : {}
}
]
}
}
]
}
}
}
Вот как вы можете вложить запрос в ES
В "bool" больше типов
нравится - 1. Фильтр 2. must_not
Ответ 6
Недавно мне тоже пришлось решить эту проблему, и после LOT проб и ошибок я придумал это (в PHP, но напрямую отображает DSL):
'query' => [
'bool' => [
'should' => [
['prefix' => ['name_first' => $query]],
['prefix' => ['name_last' => $query]],
['prefix' => ['phone' => $query]],
['prefix' => ['email' => $query]],
[
'multi_match' => [
'query' => $query,
'type' => 'cross_fields',
'operator' => 'and',
'fields' => ['name_first', 'name_last']
]
]
],
'minimum_should_match' => 1,
'filter' => [
['term' => ['state' => 'active']],
['term' => ['company_id' => $companyId]]
]
]
]
Что отображает что-то подобное в SQL:
SELECT * from <index>
WHERE (
name_first LIKE '<query>%' OR
name_last LIKE '<query>%' OR
phone LIKE '<query>%' OR
email LIKE '<query>%'
)
AND state = 'active'
AND company_id = <query>
Ключ во всем этом - это параметр minimum_should_match
. Без этого filter
полностью переопределяет should
.
Надеюсь, это поможет кому-то!
Ответ 7
$filterQuery = $this->queryFactory->create(QueryInterface::TYPE_BOOL, ['must' => $queries,'should'=>$queriesGeo]);
В must
вам нужно добавить массив условий запроса, с которым вы хотите работать AND
, а в should
вам нужно добавить условие запроса, с которым вы хотите работать OR
.
Вы можете проверить это: https://github.com/Smile-SA/elasticsuite/issues/972