[Elasticsearch] should 절에 대한 오해(와 진실까지는 모르겠고..) - should는 엄밀히 말하면 OR가 아니다

by 스뎅(thDeng) on

오해

Elasticsearch를 사용하면서 Boolean query 등에서 필터링을 위한 조건으로 mustshould가 많이 사용된다. (must_not도 있고 많지만 여기서는 should에 관한 이야기만을 다룬다.)

mustshould는 단순히 이렇게만 알고 사용했다. 아마도 빠르게 Elasticsearch를 도입해서 사용하는 많은 팀에서 이렇게 인식하고 사용하고 있을지 모른다.

많은 개발언어들이 ANDOR 같은 논리 연산자를 가지고 있고, Elasticsearch도 의례 그러려니 하는 생각과 당장의 비즈니스 문제를 해결하기 위해 필요로 하는 것만을 보는 시각에 갇혀 있었다.

다시 문서를 살펴 봤다.

“해도 좋고”의 취향반영

should는 “해도 좋고..”의 취향반영 정도의 느낌이다. 여기서 느낌이라고 표현한 것은 영어공부할 때 어려운 조동사의 그 느낌처럼 “해도 좋고..” 느낌으로 각 상황에 맞게 사용/해석해야 하는 점 때문이다. 그래서인지 should 의 옵션으로 minimum_should_match 설정이 있는데, 여러 should 절 옵션 중에 몇 개가 매칭되어야 하는지를 결정할 수 있다. should 절에 나열된 것들 중 어떤 것이든 만족해도 좋은데, 최소한 몇 개 이상이 되어야 한다는 의미로 해석하면 좋을 것 같다.

minimum_should_match 설정의 기본값은 bool 쿼리에 must 절이나 filter 절이 있으면 1, 그 이외에는 0이다. 따라서 아래와 같이 must와 함께 사용된 bool 쿼리에서는 should 절의 3개의 조건 중 하나만 만족하면 된다. 하나만 만족하면 되기 때문에 OR로 오해받는 포인트가 된다.

POST _search
{
  "query": {
    "bool" : {
      "must" : {
        "term" : { "user.id" : "kimchy" }
      },
      "should" : [
        { "term" : { "tags" : "env1" } },
        { "term" : { "tags" : "deployed" } },
        { "term" : { "tags" : "production" }
      ]
    }
  }
}

위의 쿼리에서 minimum_should_match 설정을 아래처럼 2로 바꾸면, should 절의 조건 3개 중 2개는 매칭되어야 검색이 되기 때문에 OR 라고 생각하면 안 된다. tagsenv1, deployed, production 3개 중 어떤 것이든 2개가 매칭되면 되고, OR와는 의미가 달라진다.

POST _search
{
  "query": {
    "bool" : {
      "must" : {
        "term" : { "user.id" : "kimchy" }
      },
      "should" : [
        { "term" : { "tags" : "env1" } },
        { "term" : { "tags" : "deployed" } },
        { "term" : { "tags" : "production" }
      ],
      "minimum_should_match" : 2
    }
  }
}

minimum_should_match

minimum_should_match 설정의 기본값은 1 또는 0으로 정수이지만 퍼센티지를 설정할 수도 있고, 심지어 음수까지도 가능하다. (minimum_should_match parameter - Elasticsearch Guide)

주의할 점은 비율을 사용할 때 반내림으로 인한 개수 차이이다. 75%와 -25%는 옵션이 4개일 때는 모두 3개 이상 만족하면 되지만, 옵션이 5개가 되면 75%는 3이고 -25%는 -1이 되어 4개를 만족해야 한다.

참고

별도로 명시하지 않을 경우, 이 블로그의 포스트는 다음 라이선스에 따라 사용할 수 있습니다: Creative Commons License CC Attribution-NonCommercial-ShareAlike 4.0 International License