elasticsearch bool 쿼리는 OR과 결합해야합니다


181

현재 solr 기반 응용 프로그램을 elasticsearch로 마이그레이션하려고합니다.

이 lucene 쿼리가 있습니다

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

내가 이해하는 한 이것은 부울 OR과 결합 된 MUST 절의 조합입니다.

"(이름에 foo AND bar) 또는 (info에 foo AND bar)를 포함하는 모든 문서를 가져 오십시오. 그 후 조건 state = 1로 결과를 필터링하고 이미지가있는 문서를 강화하십시오."

MUST와 함께 부울 쿼리를 사용하려고했지만 부울 OR을 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
            }
          }
        }
      ]
    }
  }
}

보시다시피 "info"에 대한 조건이 없어야합니다.

누구든지 해결책이 있습니까?

정말 고맙습니다.

** 업데이트 **

elasticsearch 쿼리를 업데이트하고 해당 기능 점수를 제거했습니다. 내 기본 문제는 여전히 존재합니다.


1
ElasticSearch 쿼리를 결합하는 좋은 문서는 다음과 같습니다. elastic.co/guide/en/elasticsearch/guide/current/…
Mr.Coffee

답변:


426
  • 또는 철자
  • AND 는 철자가 필요 합니다
  • NOR의 철자가 되어야합니다.

예:

모든 항목 (둥근 AND (빨간색 또는 파란색))을 보려고합니다.

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

보다 복잡한 OR 버전을 수행 할 수도 있습니다. 예를 들어 5 개 중 3 개 이상을 일치 시키려면 "should"에서 5 개의 옵션을 지정하고 "minimum_should"를 3으로 설정할 수 있습니다.

내 둥지가 그리 멀지 않은 곳을 찾은 Glen Thompson과 Sebastialonso에게 감사드립니다.

ElasticSearch 6에서 "term"이 "match"가된다고 지적한 Fatmajk에게도 감사드립니다.


2
작업을 포함 should하여 상위 수준으로 끌어 올릴 까요? boolminimum_should_match: 1
Sid

18
이 예제를 시도하면 다시 돌아옵니다 [term] malformed query, expected [END_OBJECT] but found [FIELD_NAME]. 이것은 어떻게 든 버전에 의존합니까?
DanneJ

26
왜 문서에 간단한 예제와 설명을 추가하지 않습니까! 문서의 예제는 매우 혼란 스럽습니다.
Nikhil Owalekar

21
6 개월 후 모든 Elastic 문서를 읽고 부울 논리 구현 방법을 완전히 이해 한 것은 이번이 처음입니다. 내 의견으로는 공식 문서가 명확하지 않습니다.
Sebastialonso

3
@Amir 어떤 부정확성을 정리할 수 있습니까? 위에 표시된 컨텍스트에서 기본값 minimum_should은 1이며, bool적어도 하나의 항목이 일치하면 해당 그룹을 래핑 하여 해당 그룹을 true로, 일치하지 않으면 false를 반환합니다. 이 답변을 만들려는 동기는 내가 정확히 이런 종류의 문제를 해결하고 있었고 사용 가능한 문서와 이와 같은 사이트에서 찾을 수있는 답변은 기껏해야 도움이되지 않았기 때문에 아주 확실하게 파악할 때까지 계속 연구했습니다. 무슨 일이 있었는지. 답변을 더 향상시킬 수있는 방법에 대한 건설적인 조언을 환영합니다.
Daniel Fackrell

69

마침내 내가 원하는 것을 정확하게 수행하는 쿼리를 만들었습니다.

필터링 된 중첩 부울 쿼리입니다. 왜 이것이 문서화되어 있지 않은지 잘 모르겠습니다. 여기 누군가 말해 줄 수 있을까요?

다음은 쿼리입니다.

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

이는 문서 필드 분석 및 name = foo가 내부적으로 처리되는 방식에 따라 달라집니다. 이는 퍼지에서 엄격한 동작까지 다양합니다.

"minimum_should_match": 1에 따르면, should 문 중 하나 이상이 true 여야합니다.

이 문장은 결과 집합에 has_image : 1을 포함하는 문서가있을 때마다 요소 100만큼 증가한다는 것을 의미합니다. 결과 순서가 변경됩니다.

"should": [
  {
    "match": {
      "has_image": {
        "query": 1,
        "boost": 100
      }
    }
   }
 ]

재밌게 놀아 :)


28
이런 세상에. 누구든지 더 나은 솔루션을 가지고 있습니까? 이것을 게시 해 주셔서 감사하지만 쿼리에서 논리적 OR을 달성하기에는 너무 복잡한 방법입니다.
nackjicholson

thnx, 당신은 내 하루를 구했다)
cubbiu

3
이 쿼리는 불필요한 긴 구문 일뿐만 아니라 더 이상 사용되지 않는 구문을 사용합니다. @ daniel-fackrell의 답변은 받아 들여야합니다.
Eric Alford 2012

4
@EricAlford 2015 년 답변은 이전 버전의 ES를 기반으로합니다. 더 나은 솔루션을 제공하십시오.
Jesse

1
아이디어 : ElasticSearch를 인수 / 포크하고 사용자 친화적 인 방식으로 다시 작성하고 간단한 쿼리 언어를 추가하십시오. 우리는 단지 자금이 필요합니다. 나는 ~ 안에있다! 그밖에 누가 ?
Sliq

16

Kibana를 사용하여 하나의 외부 부울 쿼리에 여러 부울 쿼리를 중첩시키는 방법입니다.

부울 은 우리가 부울을 사용하고 있음을 나타냅니다

AND를 위한 것이 어야한다

SHOULD을 위한 OR

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


당신의 대답은 정확히 맞습니다. 그러나 약간 어색합니다. 원한다면 작은 제안입니다. 제대로 편집해야합니다. 아마 그것은 당신 에게이 답변에 더 많은 것을 제공합니다 :) 좋은 하루 되세요.
Dhwanil Patel

6

나는 최근 에이 문제를 해결해야했고 많은 시행 착오 후에 이것을 (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.

이것이 누군가를 돕기를 바랍니다!


0
$filterQuery = $this->queryFactory->create(QueryInterface::TYPE_BOOL, ['must' => $queries,'should'=>$queriesGeo]);

에서 must당신은 당신이 작업 할 쿼리 조건 배열 추가해야 AND하고의를 should당신은 당신이 작업 할 쿼리 조건을 추가해야합니다 OR.

이것을 확인할 수 있습니다 : https://github.com/Smile-SA/elasticsuite/issues/972


0

Solr의 기본 또는 Lucene 쿼리 파서를 사용하는 경우 거의 항상 쿼리 문자열 쿼리에 넣을 수 있습니다.

POST test/_search
{
  "query": {
    "query_string": {
      "query": "(( name:(+foo +bar) OR info:(+foo +bar)  )) AND state:(1) AND (has_image:(0) OR has_image:(1)^100)"
    }
  }
}

즉, 이미 게시 한 것과 같은 부울 쿼리 를 사용 하거나 두 가지를 조합하여 사용할 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.