최소 일치(minimum_should_match)

최소 일치(minimum_should_match)

minimum_should_match 파라미터는 전체 텍스트 검색에 사용되며, 문서가 검색 결과에 반환되기 위해 일치해야 하는 최소 용어(term) 수를 지정해요.

다음 예제는 문서가 검색 결과로 반환되기 위해 세 개의 검색 용어 중 적어도 두 개와 일치해야 한다고 요구해요.

GET /shakespeare/_search
{
  "query": {
    "match": {
      "text_entry": {
        "query": "prince king star",
        "minimum_should_match": "2"
      }
    }
  }
}

이 예제에서 쿼리는 OR로 결합된 세 개의 선택 절(optional clause)을 가지므로, 문서는 prince와 king, 또는 prince와 star, 또는 king과 star 중 하나는 일치해야 해요.

출처: 문서

본문

유효한 값 (Valid values)

minimum_should_match 파라미터는 다음 값 중 하나로 지정할 수 있어요.

  • 음이 아닌 정수 (예: 2): 문서는 이 개수의 선택 절과 일치해야 해요.
  • 음의 정수 (예: -1): 문서는 전체 선택 절 수에서 이 값을 뺀 개수와 일치해야 해요.
  • 음이 아닌 백분율 (예: 70%): 문서는 전체 선택 절 수의 이 백분율과 일치해야 해요. 일치해야 하는 절의 수는 가장 가까운 정수로 내림 처리돼요.
  • 음의 백분율 (예: -30%): 문서는 전체 선택 절 수 중 이 백분율만큼 일치하지 않아도 돼요. 문서가 일치하지 않아도 되는 절의 수는 가장 가까운 정수로 내림 처리돼요.
  • 조합 (예: 2<75%): n<p% 형식의 표현이에요. 선택 절 수가 n보다 작거나 같으면 문서는 모든 선택 절과 일치해야 해요. 선택 절 수가 n보다 크면 문서는 선택 절의 p 백분율과 일치해야 해요.
  • 여러 조합 (예: 3<-1 5<50%): 공백으로 구분된 두 개 이상의 조합이에요. 각 조건은 < 기호 왼쪽의 수보다 큰 선택 절 수에 적용돼요. 이 예제에서 선택 절이 3개 이하이면 문서는 모두 일치해야 해요. 선택 절이 4개나 5개이면 문서는 하나를 제외한 모두와 일치해야 해요. 선택 절이 6개 이상이면 문서는 50%와 일치해야 해요.

n을 문서가 일치해야 하는 선택 절의 수라고 해 보죠. n을 백분율로 계산할 때 n이 1보다 작으면 1이 사용돼요. n이 선택 절 수보다 크면 선택 절 수가 사용돼요.

불리언 쿼리에서 파라미터 사용하기

불리언(Boolean) 쿼리는 선택 절을 should 절에, 필수 절을 must 절에 나열해요. 선택적으로 결과를 필터링하는 filter 절을 포함할 수도 있어요.

다음 다섯 개 문서가 들어 있는 예제 인덱스를 생각해 보겠어요.

PUT testindex/_doc/1
{
  "text": "one OpenSearch"
}
PUT testindex/_doc/2
{
  "text": "one two OpenSearch"
}
PUT testindex/_doc/3
{
  "text": "one two three OpenSearch"
}
PUT testindex/_doc/4
{
  "text": "one two three four OpenSearch"
}
PUT testindex/_doc/5
{
  "text": "OpenSearch"
}

다음 쿼리는 네 개의 선택 절을 포함해요.

GET testindex/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "text": "OpenSearch"
          }
        }
      ], 
      "should": [
        {
          "match": {
            "text": "one"
          }
        },
        {
          "match": {
            "text": "two"
          }
        },
        {
          "match": {
            "text": "three"
          }
        },
        {
          "match": {
            "text": "four"
          }
        }
      ],
      "minimum_should_match": "80%"
    }
  }
}

minimum_should_match가 80%로 지정되었으므로 일치해야 하는 선택 절 수는 4 · 0.8 = 3.2로 계산된 뒤 3으로 내림 처리돼요. 따라서 결과에는 적어도 세 개의 절과 일치하는 문서가 포함됩니다.

{
  "took": 40,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 2,
      "relation": "eq"
    },
    "max_score": 2.494999,
    "hits": [
      {
        "_index": "testindex",
        "_id": "4",
        "_score": 2.494999,
        "_source": {
          "text": "one two three four OpenSearch"
        }
      },
      {
        "_index": "testindex",
        "_id": "3",
        "_score": 1.5744598,
        "_source": {
          "text": "one two three OpenSearch"
        }
      }
    ]
  }
}

이제 minimum_should_match를 -20%로 지정해 보겠어요.

GET testindex/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "text": "OpenSearch"
          }
        }
      ], 
      "should": [
        {
          "match": {
            "text": "one"
          }
        },
        {
          "match": {
            "text": "two"
          }
        },
        {
          "match": {
            "text": "three"
          }
        },
        {
          "match": {
            "text": "four"
          }
        }
      ],
      "minimum_should_match": "-20%"
    }
  }
}

문서가 일치하지 않아도 되는 선택 절 수는 4 · 0.2 = 0.8로 계산된 뒤 0으로 내림 처리돼요. 따라서 결과에는 모든 선택 절과 일치하는 문서 하나만 포함됩니다.

{
  "took": 41,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 1,
      "relation": "eq"
    },
    "max_score": 2.494999,
    "hits": [
      {
        "_index": "testindex",
        "_id": "4",
        "_score": 2.494999,
        "_source": {
          "text": "one two three four OpenSearch"
        }
      }
    ]
  }
}

양의 백분율(80%)과 음의 백분율(-20%)을 지정해도 문서가 일치해야 하는 선택 절 수가 같지 않다는 점을 주의하세요. 두 경우 모두 결과가 내림 처리되기 때문이에요. 예를 들어 선택 절 수가 5라면 80%와 -20% 모두 문서가 일치해야 하는 선택 절 수(4)를 동일하게 만들어요.

기본 minimum_should_match 값

쿼리에 must 또는 filter 절이 포함되어 있으면 minimum_should_match의 기본값은 0이에요. 예를 들어 다음 쿼리는 OpenSearch와 0개의 선택 should 절에 일치하는 문서를 검색해요.

GET testindex/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "text": "OpenSearch"
          }
        }
      ], 
      "should": [
        {
          "match": {
            "text": "one"
          }
        },
        {
          "match": {
            "text": "two"
          }
        },
        {
          "match": {
            "text": "three"
          }
        },
        {
          "match": {
            "text": "four"
          }
        }
      ]
    }
  }
}

이 쿼리는 인덱스의 다섯 문서를 모두 반환해요.

{
  "took": 34,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 5,
      "relation": "eq"
    },
    "max_score": 2.494999,
    "hits": [
      {
        "_index": "testindex",
        "_id": "4",
        "_score": 2.494999,
        "_source": {
          "text": "one two three four OpenSearch"
        }
      },
      {
        "_index": "testindex",
        "_id": "3",
        "_score": 1.5744598,
        "_source": {
          "text": "one two three OpenSearch"
        }
      },
      {
        "_index": "testindex",
        "_id": "2",
        "_score": 0.91368985,
        "_source": {
          "text": "one two OpenSearch"
        }
      },
      {
        "_index": "testindex",
        "_id": "1",
        "_score": 0.4338556,
        "_source": {
          "text": "one OpenSearch"
        }
      },
      {
        "_index": "testindex",
        "_id": "5",
        "_score": 0.11964063,
        "_source": {
          "text": "OpenSearch"
        }
      }
    ]
  }
}

하지만 must 절을 생략하면 쿼리는 하나의 선택 should 절과 일치하는 문서를 검색해요.

GET testindex/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "match": {
            "text": "one"
          }
        },
        {
          "match": {
            "text": "two"
          }
        },
        {
          "match": {
            "text": "three"
          }
        },
        {
          "match": {
            "text": "four"
          }
        }
      ]
    }
  }
}

결과에는 선택 절 중 적어도 하나와 일치하는 네 문서만 포함돼요.

{
  "took": 19,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 4,
      "relation": "eq"
    },
    "max_score": 2.426633,
    "hits": [
      {
        "_index": "testindex",
        "_id": "4",
        "_score": 2.426633,
        "_source": {
          "text": "one two three four OpenSearch"
        }
      },
      {
        "_index": "testindex",
        "_id": "3",
        "_score": 1.4978898,
        "_source": {
          "text": "one two three OpenSearch"
        }
      },
      {
        "_index": "testindex",
        "_id": "2",
        "_score": 0.8266785,
        "_source": {
          "text": "one two OpenSearch"
        }
      },
      {
        "_index": "testindex",
        "_id": "1",
        "_score": 0.3331056,
        "_source": {
          "text": "one OpenSearch"
        }
      }
    ]
  }
}

더 알아보기 (Learn more)