2015-02-16 2 views
52

В настоящее время я пытаюсь перенести приложение на основе solr в elasticsearch.elasticsearch bool query union должен с OR

У меня есть этот Lucene запрос,

(( 
    name:(+foo +bar) 
    OR info:(+foo +bar) 
)) AND state:(1) AND (has_image:(0) OR has_image:(1)^100) 

Насколько я понимаю, что это сочетание MUST положений в сочетании с Логическим ИЛИ:

«Получить все документы, содержащие (Foo и бар в имени) ИЛИ (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 
      } 
      } 
     } 
     ] 
    } 
    } 
} 

Как вы можете видеть, ДОЛЖНЫ условия для «информации» отсутствуют.

У кого-нибудь есть решение?

Большое вам спасибо.

** UPDATE **

Я обновил свой elasticsearch запрос и избавились от этой функции балла. Моя базовая проблема все еще существует.

+0

Существует хорошая документация по объединению запросов ElasticSearch: https://www.elastic.co/guide/en/elasticsearch/guide/current/combining-filters.html –

ответ

38

я наконец-то удалось создать запрос, который делает именно то, что я хотел бы иметь:

отфильтрованный вложенную булево запрос. Я не уверен, почему это не задокументировано. Может, кто-то здесь может мне сказать?

Вот запрос:

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 
     } 
    } 
    } 
] 

Удачи ребята :)

+6

Святое дерьмо. У кого-то есть лучшее решение? Спасибо за публикацию этого, но это абсолютно слишком сложная задача для достижения логического ИЛИ в запросе. – nackjicholson

+0

Я в шоке от слабости эластичного v2 + запроса dsl ... –

+0

thnx, вы сохранили мой день) – cubbiu

2

Я недавно пришлось решать эту проблему тоже, и после того, как много проб и ошибок я пришел с этим (в 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.

Надеюсь, это поможет кому-то!

98
  • ИЛИ пишется "должен"
  • И пишется "должен"
  • NOR пишется "should_not"

Пример:

Вы хотите увидеть все элементы, (круглый И (красный ИЛИ синий)):

{ 
    "query": { 
     "bool": { 
      "must": [ 
       { 
        "term": {"shape": "round"}, 
        "bool": { 
         "should": [ 
          {"term": {"color": "red"}}, 
          {"term": {"color": "blue"}} 
         ] 
        } 
       } 
      ] 
     } 
    } 
} 

Вы также можете выполнять более сложные версии OR, например, если вы хотите совместить не менее 3 из 5, вы можете указать 5 опций под «should» и установить «minimum_should» из 3.

+1

Я считаю, что это должен быть принятый ответ. Это, кажется, самое простое решение проблемы. Спасибо. –

+2

Потянул бы 'should' в верхний уровень' bool' и включил 'minimum_should_match: 1' работу? – Sid

+0

@ Сид Это не так. В этом случае нам понадобится только {«shape»: «round»}, а «should» будет применять порядок к результатам, имеющим форму раунда, потому что на этом уровне это необязательно. Мы можем сделать это только за счет гнездования под «must». –

0

Использование вышеуказанного Я получаю

[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"}} 
        ] 
       }} 
      ] 
     } 
    } 
} 
Смежные вопросы