development

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

big-blog 2020. 6. 24. 07:10
반응형

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


현재 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 쿼리를 업데이트하고 해당 기능 점수를 제거했습니다. 내 기본 문제는 여전히 존재합니다.


  • 또는 철자
  • 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에게도 감사드립니다.


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

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

다음은 쿼리입니다.

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 문이 참이어야한다고 말합니다.

This statements means that whenever there is a document in the resultset that contains has_image:1 it is boosted by factor 100. This changes result ordering.

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

Have fun guys :)


Using the above I get

[term] malformed query, expected [END_OBJECT] but found [FIELD_NAME]

This worked for me

Updated for Elasticsearch 5.6.4 +

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

ElasticSearch is definitely horrible when it comes to simple queries like AND, OR or IN. But, you can go the smart way and write your query as SQL and then convert it to ElasticSearch syntax with this excellent online tool:

SQL to ElasticSearch converter

https://www.toolsbuzz.com/query-converter

You can thank me later :)


This is how you can nest multiple bool queries in one outer bool query this using 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" : {} 
                                 }     
                               ]
                          }
                 }
             ]
        }
    }
}

This is how you can nest a query in ES There are more types in "bool" like - 1. Filter 2. must_not


I recently had to solve this problem too, and after a LOT of trial and error I came up with this (in PHP, but maps directly to the 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]]
        ]
    ]
]

Which maps to something like this in 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>

The key in all this is the minimum_should_match setting. Without this the filter totally overrides the should.

Hope this helps someone!


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

In must you need to add the query condition array which you want to work with AND and in should you need to add the query condition which you want to work with OR.

You can check this: https://github.com/Smile-SA/elasticsuite/issues/972

참고URL : https://stackoverflow.com/questions/28538760/elasticsearch-bool-query-combine-must-with-or

반응형