Boolean 쿼리

Boolean 쿼리

Boolean(bool) 쿼리는 여러 쿼리 절을 하나의 고급 쿼리로 결합할 수 있어요. 절들이 Boolean 논리로 결합되어 결과에 반환되는 일치 문서를 찾습니다.

출처: 문서

본문

Boolean(bool) 쿼리는 여러 쿼리 절을 하나의 고급 쿼리로 결합할 수 있어요. 절들은 Boolean 논리로 결합되어 결과에 반환되는 일치 문서를 찾아요.

bool 쿼리 안에서 다음 쿼리 절을 사용하세요.

절 동작
must 논리 AND 연산자. 결과는 이 절의 모든 쿼리와 일치해야 해요.
must_not 논리 NOT 연산자. 모든 일치 항목은 결과에서 제외돼요. must_not이 여러 절을 가지면, 그 어떤 절과도 일치하지 않는 문서만 반환돼요. 예를 들어 "must_not":[{clause_A}, {clause_B}]는 NOT(A OR B)와 동일해요.
should 논리 OR 연산자. 결과는 쿼리 중 적어도 하나와 일치해야 해요. 더 많은 should 절을 일치시킬수록 문서의 관련성 점수가 높아져요. minimum_should_match 파라미터를 사용해 일치해야 하는 최소 쿼리 수를 설정할 수 있어요. 쿼리에 must 또는 filter 절이 포함되어 있으면 기본 minimum_should_match 값은 0이에요. 그렇지 않으면 기본 minimum_should_match 값은 1이에요.
filter 쿼리를 적용하기 전에 먼저 적용되어 데이터셋을 줄이는 논리 AND 연산자. filter 절 안의 쿼리는 예/아니오 옵션이에요. 문서가 쿼리와 일치하면 결과에 반환되고, 그렇지 않으면 반환되지 않아요. filter 쿼리의 결과는 일반적으로 더 빠른 반환을 위해 캐시돼요. 정확히 일치, 범위, 날짜, 숫자를 기준으로 결과를 필터링하려면 filter 쿼리를 사용하세요.

Boolean 쿼리는 다음과 같은 구조를 가져요.

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

예를 들어 OpenSearch 클러스터에 셰익스피어 전집이 인덱싱되어 있다고 가정해 볼게요. 다음 요구 사항을 충족하는 단일 쿼리를 만들고 싶어요:

  • text_entry 필드는 단어 love를 포함해야 하고 life 또는 grace 중 하나를 포함해야 해요.
  • speaker 필드는 ROMEO를 포함하면 안 돼요.
  • 관련성 점수에 영향을 주지 않고 결과를 Romeo and Juliet 희곡으로 필터링해요.

이 요구 사항들은 다음 쿼리에서 결합할 수 있어요.

GET shakespeare/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "text_entry": "love"
          }
        }
      ],
      "should": [
        {
          "match": {
            "text_entry": "life"
          }
        },
        {
          "match": {
            "text_entry": "grace"
          }
        }
      ],
      "minimum_should_match": 1,
      "must_not": [
        {
          "match": {
            "speaker": "ROMEO"
          }
        }
      ],
      "filter": {
        "term": {
          "play_name": "Romeo and Juliet"
        }
      }
    }
  }
}

응답에는 일치하는 문서가 포함돼요.

{
  "took": 12,
  "timed_out": false,
  "_shards": {
    "total": 4,
    "successful": 4,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 1,
      "relation": "eq"
    },
    "max_score": 11.356054,
    "hits": [
      {
        "_index": "shakespeare",
        "_id": "88020",
        "_score": 11.356054,
        "_source": {
          "type": "line",
          "line_id": 88021,
          "play_name": "Romeo and Juliet",
          "speech_number": 19,
          "line_number": "4.5.61",
          "speaker": "PARIS",
          "text_entry": "O love! O life! not life, but love in death!"
        }
      }
    ]
  }
}

이 절들 중 어떤 절이 실제로 매칭 결과를 일으켰는지 확인하고 싶다면 _name 파라미터로 각 쿼리에 이름을 지정하세요. _name 파라미터를 추가하려면 match 쿼리의 필드 이름을 객체로 바꾸면 돼요.

GET shakespeare/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "text_entry": {
              "query": "love",
              "_name": "love-must"
            }
          }
        }
      ],
      "should": [
        {
          "match": {
            "text_entry": {
              "query": "life",
              "_name": "life-should"
            }
          }
        },
        {
          "match": {
            "text_entry": {
              "query": "grace",
              "_name": "grace-should"
            }
          }
        }
      ],
      "minimum_should_match": 1,
      "must_not": [
        {
          "match": {
            "speaker": {
              "query": "ROMEO",
              "_name": "ROMEO-must-not"
            }
          }
        }
      ],
      "filter": {
        "term": {
          "play_name": "Romeo and Juliet"
        }
      }
    }
  }
}

OpenSearch는 이 결과와 일치한 쿼리를 나열하는 matched_queries 배열을 반환해요.

"matched_queries": [
  "love-must",
  "life-should"
]

이 목록에 없는 쿼리를 제거해도 정확히 같은 결과를 볼 수 있어요. 어떤 should 절이 일치했는지 살펴보면 결과의 관련성 점수를 더 잘 이해할 수 있어요.

bool 쿼리를 중첩해 복잡한 Boolean 표현식을 구성할 수도 있어요. 예를 들어 다음 쿼리를 사용해 Romeo and Juliet 희곡에서 (love OR hate) AND (life OR grace)와 일치하는 text_entry 필드를 찾을 수 있어요.

GET shakespeare/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "bool": {
            "should": [
              {
                "match": {
                  "text_entry": "love"
                }
              },
              {
                "match": {
                  "text": "hate"
                }
              }
            ]
          }
        },
        {
          "bool": {
            "should": [
              {
                "match": {
                  "text_entry": "life"
                }
              },
              {
                "match": {
                  "text": "grace"
                }
              }
            ]
          }
        }
      ],
      "filter": {
        "term": {
          "play_name": "Romeo and Juliet"
        }
      }
    }
  }
}

응답에는 일치하는 문서가 포함돼요.

{
  "took": 10,
  "timed_out": false,
  "_shards": {
    "total": 2,
    "successful": 2,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": 1,
    "max_score": 11.37006,
    "hits": [
      {
        "_index": "shakespeare",
        "_type": "doc",
        "_id": "88020",
        "_score": 11.37006,
        "_source": {
          "type": "line",
          "line_id": 88021,
          "play_name": "Romeo and Juliet",
          "speech_number": 19,
          "line_number": "4.5.61",
          "speaker": "PARIS",
          "text_entry": "O love! O life! not life, but love in death!"
        }
      }
    ]
  }
}

더 알아보기 (Learn more)