2.X/2. Search in Depth

2-1-2. Combining Filters

drscg 2017. 9. 30. 02:25

The previous two examples showed a single filter in use. In practice, you will probably need to filter on multiple values or fields. For example, how would you express this SQL in Elasticsearch?

앞의 두 가지 예제는 단일 filter의 사용을 보여준다. 실제 상황에서는, 아마도 여러 값 또는 field를 filtering해야 할 것이다. 예를 들면, 아래의 SQL을 Elasticsearch에서는 어떻게 표현할까?

SELECT product
FROM   products
WHERE  (price = 20 OR productID = "XHDK-A-1293-#fJ3")
  AND  (price != 30)

In these situations, you will need to use a bool query inside the constant_score query. This allows us to build filters that can have multiple components in boolean combinations.

이 상황에서는, constant_score query 내에 bool query가 필요하다. 이것으로 boolean 조합에서 다양한 요소를 가질 수 있는 filter를 만들 수 있다.

Bool Filteredit

Recall that the bool query is composed of four sections:

bool query는 4가지 부분으로 구성되어 있다는 것을 기억하자.

{
   "bool" : {
      "must" :     [],
      "should" :   [],
      "must_not" : [],
      "filter":    []
   }
}
must

All of these clauses must match. The equivalent of AND.

이 절 모두는 반드시 일치해야 한다. AND 와 동일하다.

must_not

All of these clauses must not match. The equivalent of NOT.

이 절 모두는 반드시 일치하지 않아야 한다. NOT 과 동일하다.

should

At least one of these clauses must match. The equivalent of OR.

이 절 중 최소한 하나는 반드시 일치해야 한다. OR 와 동일하다.

filter

Clauses that must match, but are run in non-scoring, filtering mode.

반드시 일치해야 하는 절이나 score를 계산하지 않는 filtering mode이다.

In this secondary boolean query, we can ignore the filter clause: the queries are already running in non-scoring mode, so the extra filter clause is useless.

이 부차적인 boolean query에서, filter 절은 무시할 수 있다. query는 이미 non-scoring 모드이다. 따라서 추가적인 filter 절은 불필요하다.

Note

Each section of the bool filter is optional (for example, you can have a must clause and nothing else), and each section can contain a single query or an array of queries.

bool filter의 각 부분은 선택적이고,(예: 다른 것은 없이, must 절만 가질 수 있다) 그리고, 각 부분은 단일 query나 query의 배열을 가질 수 있다.

To replicate the preceding SQL example, we will take the two term queries that we used previously and place them inside the should clause of a bool query, and add another clause to deal with the NOT condition:

위의 SQL 예제를 복제하기 위해서, 이전에 사용했던 term query 2개를 가져오고, 그것들을 bool query의 should 절 내부에 둔다. 그리고 NOT 조건을 위해, 다른 절을 추가한다.

GET /my_store/products/_search
{
   "query" : {
      "constant_score" : { 
         "filter" : {
            "bool" : {
              "should" : [
                 { "term" : {"price" : 20}}, 
                 { "term" : {"productID" : "XHDK-A-1293-#fJ3"}} 
              ],
              "must_not" : {
                 "term" : {"price" : 30} 
              }
           }
         }
      }
   }
}

filter 절을 모두 감싸기 위해, constant_score query를 사용해야 한다는 것을 기억하자. 이것은 non-scoring mode를 활성화한다.

 

이들 2개의 term query는 bool query의 자식(children) 이다. 그리고 should 절 내부에 있기 때문에, 최소한 하나 이상이 일치해야 한다.

만약 상품의 가격이 30 이라면, must_not 절에 일치하기 때문에 자동으로 제외된다.

Notice how boolean is placed inside the constant_score, but the individual term queries are just placed in the should and must_not. Because everything is wrapped with the constant_score, the rest of the queries are executing in filtering mode.

boolean은 constant_score 내부에 위치하지만 각각의 term query는 should 와 must_not 에만 위치한다는 점을 주목하자. 모든 것이 constant_score 로 감싸져 있기 때문에, 나머지 query는 filtering mode에서 실행된다.

Our search results return two hits, each document satisfying a different clause in the bool query:

검색 결과는 2개의 hit를 반환한다. 각 document는 bool query의 서로 다른 절을 만족한다.

"hits" : [
    {
        "_id" :     "1",
        "_score" :  1.0,
        "_source" : {
          "price" :     10,
          "productID" : "XHDK-A-1293-#fJ3" 
        }
    },
    {
        "_id" :     "2",
        "_score" :  1.0,
        "_source" : {
          "price" :     20, 
          "productID" : "KDKE-B-9947-#kL5"
        }
    }
]

productID = "XHDK-A-1293-#fJ3" 라는 term query에 일치한다.

price = 20 이라는 term query에 일치한다.

Nesting Boolean Queriesedit

You can already see how nesting boolean queries together can give rise to more sophisticated boolean logic. If you need to perform more complex operations, you can continue nesting boolean queries in any combination, giving rise to arbitrarily complex boolean logic.

내장된 boolean query로 더 복잡한 boolean logic을 만드는 방법을 이미 알고 있다. 더 복잡한 연산의 수행이 필요하다면, 임의의 복잡한 boolean logic을 만들기 위해, 어떤 조합에 내장된 boolean query를 계속 넣을 수 있다.

For example, if we have this SQL statement:

아래 SQL을 보자.

SELECT document
FROM   products
WHERE  productID      = "KDKE-B-9947-#kL5"
  OR (     productID = "JODL-X-1937-#pV7"
       AND price     = 30 )

We can translate it into a pair of nested bool filters:

이것을 내장된 bool filter의 쌍으로 바꾸어 보자.

GET /my_store/products/_search
{
   "query" : {
      "constant_score" : {
         "filter" : {
            "bool" : {
              "should" : [
                { "term" : {"productID" : "KDKE-B-9947-#kL5"}}, 
                { "bool" : { 
                  "must" : [
                    { "term" : {"productID" : "JODL-X-1937-#pV7"}}, 
                    { "term" : {"price" : 30}} 
                  ]
                }}
              ]
           }
         }
      }
   }
}

 

term 과 bool 은 boolean should 내의 형제 절이므로, document가 이들 query 중 최소한 하나와 반드시 일치해야 hit가 될 것이다.

 

must 절에서는 2개의 term 절이 형제이다. 따라서 2개 모두 document와 일치해야 hit로서 반환될 것이다.

The results show us two documents, one matching each of the should clauses:

결과는, 각 should 절에 하나씩 일치하여, 2개의 document를 보여줄 것이다.

"hits" : [
    {
        "_id" :     "2",
        "_score" :  1.0,
        "_source" : {
          "price" :     20,
          "productID" : "KDKE-B-9947-#kL5" 
        }
    },
    {
        "_id" :     "3",
        "_score" :  1.0,
        "_source" : {
          "price" :      30, 
          "productID" : "JODL-X-1937-#pV7" 
        }
    }
]

productID 는 첫 번째 bool 의 term 에 일치한다.

 

이들 두 filed는 내장된 bool 의 term filter에 일치한다.

This was a simple example, but it demonstrates how Boolean queries can be used as building blocks to construct complex logical conditions.

이것은 간단한 예제이다. 그러나, boolean query를 복잡한 논리조건을 구성하는 구성 요소로 사용할 수 있는 방법을 보여주는 예제이다.


'2.X > 2. Search in Depth' 카테고리의 다른 글

2-1. Structured Search  (0) 2017.09.30
2-1-1. Finding Exact Values  (0) 2017.09.30
2-1-3. Finding Multiple Exact Values  (0) 2017.09.30
2-1-4. Ranges  (0) 2017.09.30
2-1-5. Dealing with Null Values  (0) 2017.09.30