Significant text 집계

Significant text 집계

significant_text 집계는 자유 텍스트 필드에서 비정상적이거나 흥미로운 term을 식별해요. foreground 집합(쿼리 결과)의 term 빈도를 background 집합(전체 인덱스)과 비교해요. 색인된 keyword 필드에 대해 동작하는 significant_terms와 달리, significant_text는 소스 텍스트를 즉시 재분석하고, 그렇지 않으면 결과를 왜곡할 수 있는 중복 콘텐츠를 필터링할 수 있어요.

대규모 결과 집합을 재분석하는 것은 CPU 집약적이에요. significant_text는 sampler 또는 diversified_sampler 집계 안에서 사용해 분석을 소수의 최상위 일치 문서 선택(예: 100–200개)으로 제한하세요.

출처: 문서

본문

파라미터 (Parameters)

significant_text 집계는 다음 파라미터를 받아요.

파라미터 필수/선택 데이터 타입 설명
field 필수 String 분석할 텍스트 필드.
size 선택 Integer 반환할 term 버킷 수. 기본값은 10이에요.
shard_size 선택 Integer 각 샤드에서 수집되는 후보 term 수. 값이 높을수록 정확도가 향상되지만 성능이 저하돼요. 기본값은 -1(자동 추정)이에요.
min_doc_count 선택 Integer term이 포함되기 위해 나타나야 하는 최소 문서 수. 기본값은 3이에요. 1로 설정하면 오타와 철자 오류가 반환되는 경향이 있어요.
shard_min_doc_count 선택 Integer term이 후보로 간주되기 위한 최소 로컬 샤드 빈도. 기본값은 1이에요.
background_filter 선택 Object 비교에 사용되는 background 집합을 좁히는 쿼리. 기본적으로 전체 인덱스가 background로 사용돼요.
filter_duplicate_text 선택 Boolean true면 이미 본 6개 이상의 토큰 시퀀스를 필터링해 복사-붙여넣기 콘텐츠의 노이즈를 줄여요. 기본값은 false예요.
source_fields 선택 Array 텍스트가 분석되는 JSON 소스 필드 이름 목록. 색인된 필드 이름이 소스 필드와 다를 때 사용해요(예: copy_to 사용).
include 선택 String 또는 Array 포함할 정규 표현식 패턴 또는 정확한 term 목록.
exclude 선택 String 또는 Array 결과에서 제외할 정규 표현식 패턴 또는 정확한 term 목록.

예제 (Example)

다음 예제는 Shakespeare의 전체 작품을 담고 text_entry 텍스트 필드가 있는 shakespeare 인덱스를 가정해요. 쿼리는 "breathe"를 포함하는 문서를 검색한 다음 sampler 안에서 significant_text를 사용해 전체 말뭉치와 비교할 때 해당 구절과 가장 강하게 연관된 term을 발견해요:

GET /shakespeare/_search
{
  "size": 0,
  "query": {
    "match": {
      "text_entry": "breathe"
    }
  },
  "aggs": {
    "sample": {
      "sampler": {
        "shard_size": 100
      },
      "aggs": {
        "keywords": {
          "significant_text": {
            "field": "text_entry",
            "min_doc_count": 4
          }
        }
      }
    }
  }
}

응답은 "air", "dead", "life" 같은 term이 호흡에 관한 구절과 유의미하게 연관된 것으로 식별해요:

{
  "took" : 44,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 59,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [ ]
  },
  "aggregations" : {
    "sample" : {
      "doc_count" : 59,
      "keywords" : {
        "doc_count" : 59,
        "bg_count" : 111396,
        "buckets" : [
          {
            "key" : "breathe",
            "doc_count" : 59,
            "score" : 1887.0677966101694,
            "bg_count" : 59
          },
          {
            "key" : "air",
            "doc_count" : 4,
            "score" : 2.641295376716233,
            "bg_count" : 189
          },
          {
            "key" : "dead",
            "doc_count" : 4,
            "score" : 0.9665839666414213,
            "bg_count" : 495
          },
          {
            "key" : "life",
            "doc_count" : 5,
            "score" : 0.9090787433467572,
            "bg_count" : 805
          }
        ]
      }
    }
  }
}

예제: 필터로 background 좁히기 (Example: Narrowing the background with a filter)

기본적으로 term 빈도는 전체 인덱스와 비교돼요. background_filter 파라미터는 비교 집합을 좁혀 특정 컨텍스트 안에서 유의미한 term을 드러낼 수 있어요. 다음 예제는 "breathe" 구절을 전체 말뭉치가 아닌 "Henry IV"의 대사와만 비교해요:

GET /shakespeare/_search
{
  "size": 0,
  "query": {
    "match": {
      "text_entry": "breathe"
    }
  },
  "aggs": {
    "sample": {
      "sampler": {
        "shard_size": 100
      },
      "aggs": {
        "keywords": {
          "significant_text": {
            "field": "text_entry",
            "min_doc_count": 3,
            "background_filter": {
              "term": {
                "play_name": "Henry IV"
              }
            }
          }
        }
      }
    }
  }
}

background가 3,205줄(Henry IV만)로 좁혀지면 bg_count 값이 작아지고 점수도 그에 따라 바뀌어요:

{
  "took" : 83,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 59,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [ ]
  },
  "aggregations" : {
    "sample" : {
      "doc_count" : 59,
      "keywords" : {
        "doc_count" : 59,
        "bg_count" : 3205,
        "buckets" : [
          {
            "key" : "breathe",
            "doc_count" : 59,
            "score" : 533.1666666666666,
            "bg_count" : 6
          },
          {
            "key" : "air",
            "doc_count" : 4,
            "score" : 4.842669730920234,
            "bg_count" : 3
          },
          {
            "key" : "dead",
            "doc_count" : 4,
            "score" : 1.0653879300819835,
            "bg_count" : 13
          }
        ]
      }
    }
  }
}

응답 본문 필드 (Response body fields)

필드 데이터 타입 설명
doc_count Integer 샘플의 문서 수(sampler 레벨) 또는 foreground 집합의 문서 수(significant_text 레벨).
bg_count Integer 비교에 사용되는 background 집합의 총 문서 수.
buckets Array score 내림차순으로 정렬된 유의미한 term 버킷.
buckets.key String 유의미한 term.
buckets.doc_count Integer 이 term을 포함하는 foreground 집합의 문서 수.
buckets.score Double 이 term이 background에 비해 foreground에서 얼마나 더 자주 나타나는지를 나타내는 유의미도 점수.
buckets.bg_count Integer 이 term을 포함하는 background 집합의 문서 수.

유의미도 휴리스틱 (Significance heuristics)

기본적으로 유의미도 점수는 Johnson-Laird와 Hinkley(JLH) 휴리스틱을 사용해요. field와 함께 파라미터로 이름을 추가해 대체 점수 알고리즘을 선택할 수 있어요. 다음 휴리스틱이 지원돼요.

휴리스틱 파라미터 설명
JLH jlh: {} 기본값. foreground와 background 사이의 상대적 인기 변화를 측정해요.
Mutual information mutual_information: {} term의 존재가 foreground 집합에 속하는 것에 대해 제공하는 정보의 양을 측정해요. include_negatives와 background_is_superset 옵션을 지원해요.
Chi-square chi_square: {} term과 foreground 집합 사이의 독립성을 위한 표준 통계 검정. include_negatives와 background_is_superset 옵션을 지원해요.
GND gnd: {} Google Normalized Distance. 동시발생 비율을 사용해 통계적 연관을 측정해요. background_is_superset 옵션을 지원해요.

다음 예제는 기본 JLH 대신 chi-square 점수를 사용해요:

GET /shakespeare/_search
{
  "size": 0,
  "query": {
    "match": {
      "text_entry": "breathe"
    }
  },
  "aggs": {
    "sample": {
      "sampler": {
        "shard_size": 100
      },
      "aggs": {
        "keywords": {
          "significant_text": {
            "field": "text_entry",
            "min_doc_count": 4,
            "chi_square": {}
          }
        }
      }
    }
  }
}

응답은 같은 term이 식별되지만 점수 척도가 다름을 보여줘요:

{
  "took" : 19,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 59,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [ ]
  },
  "aggregations" : {
    "sample" : {
      "doc_count" : 59,
      "keywords" : {
        "doc_count" : 59,
        "bg_count" : 111396,
        "buckets" : [
          {
            "key" : "breathe",
            "doc_count" : 59,
            "score" : 111396.0,
            "bg_count" : 59
          },
          {
            "key" : "air",
            "doc_count" : 4,
            "score" : 152.27540220402065,
            "bg_count" : 189
          },
          {
            "key" : "dead",
            "doc_count" : 4,
            "score" : 53.556852313941825,
            "bg_count" : 495
          },
          {
            "key" : "life",
            "doc_count" : 5,
            "score" : 49.44532193700098,
            "bg_count" : 805
          }
        ]
      }
    }
  }
}

제한 사항 (Limitations)

significant_text 집계에는 다음과 같은 제한 사항이 있어요:

  • 메모리 비용이 높기 때문에 하위 집계를 지원하지 않아요. 특정 term을 더 분석하려면 초기 결과의 유의미한 term을 포함하는 include 절과 함께 terms 집계로 별도 쿼리를 실행하세요.
  • 문서 JSON 소스로 동작하므로 중첩 객체를 지원하지 않아요.
  • 각 샤드가 독립적으로 보고되고 개수가 조정 노드에서 결합되므로 문서 수에 사소한 부정확성이 있을 수 있어요. 성능을 희생하고 정밀도를 향상시키려면 shard_size를 늘리세요. 기본적으로 shard_size는 -1로 설정되어 샤드 수와 size 파라미터를 자동으로 추정해요.

더 알아보기 (Learn more)