검색 요청 시 정의

원본 보기

검색 요청 시 정의

검색 요청에 runtime_mappings 섹션을 지정하면 해당 쿼리의 일부로만 존재하는 런타임 필드를 만들 수 있습니다. 매핑에 런타임 필드를 추가할 때와 마찬가지로 runtime_mappings 섹션의 일부로 스크립트를 지정합니다.

검색 요청에서 런타임 필드를 정의하는 형식은 인덱스 매핑에서 런타임 필드를 정의하는 형식과 동일합니다. 인덱스 매핑의 runtime에 있는 필드 정의를 검색 요청의 runtime_mappings 섹션으로 복사하면 됩니다.

다음 검색 요청은 runtime_mappings 섹션에 day_of_week 필드를 추가합니다. 필드 값은 동적으로 계산되며, 이 검색 요청의 컨텍스트 안에서만 유효합니다:

				GET my-index-000001/_search
					{
  "runtime_mappings": {
    "day_of_week": {
      "type": "keyword",
      "script": {
        "source": "emit(doc['@timestamp'].value.dayOfWeekEnum.getDisplayName(TextStyle.FULL, Locale.ENGLISH))"
      }
    }
  },
  "aggs": {
    "day_of_week": {
      "terms": {
        "field": "day_of_week"
      }
    }
  }
}
		

더 나아가 다른 런타임 필드의 값을 반환하는 런타임 필드를 검색 요청에서 정의할 수도 있습니다. 예를 들어 센서 데이터를 벌크 인덱싱했다고 가정해 보겠습니다:

				POST my-index-000001/_bulk?refresh=true
					{"index":{}}
{"@timestamp":1516729294000,"model_number":"QVKC92Q","measures":{"voltage":"5.2","start": "300","end":"8675309"}}
{"index":{}}
{"@timestamp":1516642894000,"model_number":"QVKC92Q","measures":{"voltage":"5.8","start": "300","end":"8675309"}}
{"index":{}}
{"@timestamp":1516556494000,"model_number":"QVKC92Q","measures":{"voltage":"5.1","start": "300","end":"8675309"}}
{"index":{}}
{"@timestamp":1516470094000,"model_number":"QVKC92Q","measures":{"voltage":"5.6","start": "300","end":"8675309"}}
{"index":{}}
{"@timestamp":1516383694000,"model_number":"HG537PU","measures":{"voltage":"4.2","start": "400","end":"8625309"}}
{"index":{}}
{"@timestamp":1516297294000,"model_number":"HG537PU","measures":{"voltage":"4.0","start": "400","end":"8625309"}}
		

인덱싱을 마친 뒤에야 숫자 데이터가 text 타입으로 매핑되었다는 것을 알게 되었습니다. measures.startmeasures.end 필드로 집계를 수행하고 싶지만, text 타입 필드로는 집계할 수 없기 때문에 집계가 실패합니다. 이럴 때 런타임 필드가 해결책이 됩니다! 인덱싱된 필드와 같은 이름의 런타임 필드를 추가하고 데이터 타입을 수정할 수 있습니다:

				PUT my-index-000001/_mapping
					{
  "runtime": {
    "measures.start": {
      "type": "long"
    },
    "measures.end": {
      "type": "long"
    }
  }
}
		

런타임 필드는 인덱스 매핑에 정의된 동일한 이름의 필드보다 우선합니다. 이러한 유연성 덕분에 필드 자체를 수정하지 않고도 기존 필드를 가리고 다른 값을 계산할 수 있습니다. 인덱스 매핑에 실수가 있었다면, 런타임 필드를 사용해 검색 요청 중에 매핑의 값을 재정의하는 값을 계산할 수 있습니다.

이제 measures.startmeasures.end 필드에 평균 집계를 손쉽게 실행할 수 있습니다:

				GET my-index-000001/_search
					{
  "aggs": {
    "avg_start": {
      "avg": {
        "field": "measures.start"
      }
    },
    "avg_end": {
      "avg": {
        "field": "measures.end"
      }
    }
  }
}
		

응답에는 기반 데이터의 값을 변경하지 않은 채 집계 결과가 포함됩니다:

{
  "aggregations" : {
    "avg_start" : {
      "value" : 333.3333333333333
    },
    "avg_end" : {
      "value" : 8658642.333333334
    }
  }
}
		

또한 값을 계산하는 런타임 필드를 검색 쿼리의 일부로 정의한 다음, 같은 쿼리 안에서 그 필드에 통계 집계를 실행할 수 있습니다.

duration 런타임 필드는 인덱스 매핑에 존재하지 않지만, 그래도 해당 필드로 검색하고 집계할 수 있습니다. 다음 쿼리는 duration 필드의 계산된 값을 반환하고, 집계된 문서에서 추출한 숫자 값에 대한 통계를 계산하는 stats 집계를 실행합니다.

				GET my-index-000001/_search
					{
  "runtime_mappings": {
    "duration": {
      "type": "long",
      "script": {
        "source": """
          emit(doc['measures.end'].value - doc['measures.start'].value);
          """
      }
    }
  },
  "aggs": {
    "duration_stats": {
      "stats": {
        "field": "duration"
      }
    }
  }
}
		

duration 런타임 필드는 검색 쿼리의 컨텍스트 안에서만 존재하지만, 그 필드로 검색하고 집계할 수 있습니다. 이러한 유연성은 매우 강력해서, 인덱스 매핑의 실수를 바로잡고 단일 검색 요청 안에서 계산을 동적으로 완료할 수 있게 해줍니다.

{
  "aggregations" : {
    "duration_stats" : {
      "count" : 6,
      "min" : 8624909.0,
      "max" : 8675009.0,
      "avg" : 8658309.0,
      "sum" : 5.1949854E7
    }
  }
}