Search Templates API
Search Templates API
전체 텍스트 쿼리를 검색 템플릿으로 변환하면 사용자 입력을 받아 쿼리에 동적으로 삽입할 수 있어요.
예를 들어 OpenSearch를 애플리케이션이나 웹사이트의 백엔드 검색 엔진으로 사용한다면, 검색 바나 폼 필드에서 사용자 쿼리를 받아 검색 템플릿에 파라미터로 전달할 수 있어요. 이렇게 하면 OpenSearch 쿼리를 만드는 구문이 엔드 유저로부터 추상화돼요.
사용자 입력을 OpenSearch 쿼리로 변환하는 코드를 작성할 때 검색 템플릿으로 코드를 단순화할 수 있어요. 검색 쿼리에 필드를 추가해야 한다면 코드를 수정하지 않고 템플릿만 수정하면 되죠.
검색 템플릿은 Mustache 언어를 사용해요. 모든 구문 옵션의 목록은 Mustache 수동을 참고하세요.
검색 템플릿 생성
검색 템플릿에는 쿼리와 파라미터 두 가지 구성 요소가 있어요. 파라미터는 변수에 들어가는 사용자가 입력한 값이에요. 변수는 Mustache 표기법에서 이중 중괄호로 표현돼요. 쿼리에서 {{var}} 같은 변수를 만나면 OpenSearch는 params 섹션으로 가서 var라는 파라미터를 찾아 지정된 값으로 대체해요.
애플리케이션을 코딩해 사용자에게 무엇을 검색할지 물어본 다음, 실행 시점에 그 값을 params 객체에 넣을 수 있어요.
다음 명령은 이름으로 희곡(play)을 찾는 검색 템플릿을 정의해요. 쿼리의 {{play_name}}은 Henry IV 값으로 대체돼요:
GET /_search/template
{
"source": {
"query": {
"match": {
"play_name": "{{play_name}}"
}
}
},
"params": {
"play_name": "Henry IV"
}
}
이 템플릿은 전체 클러스터에서 검색을 실행해요. 특정 인덱스에서 검색을 실행하려면 요청에 인덱스 이름을 추가하세요:
GET /shakespeare/_search/template
from과 size 파라미터를 지정해요:
GET /_search/template
{
"source": {
"from": "{{from}}",
"size": "{{size}}",
"query": {
"match": {
"play_name": "{{play_name}}"
}
}
},
"params": {
"play_name": "Henry IV",
"from": 10,
"size": 10
}
}
검색 경험을 개선하려면 사용자가 모든 파라미터를 지정하지 않아도 되도록 기본값을 정의할 수 있어요. 파라미터가 params 섹션에 정의되지 않으면 OpenSearch는 기본값을 사용해요.
변수 var의 기본값을 정의하는 구문은 다음과 같아요:
{{var}}{{^var}}default value{{/var}}
다음 명령은 from의 기본값을 10으로, size의 기본값을 10으로 설정해요:
GET /_search/template
{
"source": {
"from": "{{from}}{{^from}}10{{/from}}",
"size": "{{size}}{{^size}}10{{/size}}",
"query": {
"match": {
"play_name": "{{play_name}}"
}
}
},
"params": {
"play_name": "Henry IV"
}
}
검색 템플릿 저장 및 실행
검색 템플릿이 원하는 대로 동작하면 그 템플릿의 소스를 스크립트로 저장해, 서로 다른 입력 파라미터에 재사용할 수 있게 만들 수 있어요.
검색 템플릿을 스크립트로 저장할 때는 lang 파라미터를 mustache로 지정해야 해요:
POST _scripts/play_search_template
{
"script": {
"lang": "mustache",
"source": {
"from": "{{from}}{{^from}}0{{/from}}",
"size": "{{size}}{{^size}}10{{/size}}",
"query": {
"match": {
"play_name": "{{play_name}}"
}
}
},
"params": {
"play_name": "Henry IV"
}
}
}
이제 이 템플릿의 id 파라미터를 참조해 재사용할 수 있어요. 이 소스 템플릿을 서로 다른 입력 값에 재사용할 수 있죠:
GET /_search/template
{
"id": "play_search_template",
"params": {
"play_name": "Henry IV",
"from": 0,
"size": 1
}
}
예제 응답
{
"took": 7,
"timed_out": false,
"_shards": {
"total": 6,
"successful": 6,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 3205,
"relation": "eq"
},
"max_score": 3.641852,
"hits": [
{
"_index": "shakespeare",
"_type": "_doc",
"_id": "4",
"_score": 3.641852,
"_source": {
"type": "line",
"line_id": 5,
"play_name": "Henry IV",
"speech_number": 1,
"line_number": "1.1.2",
"speaker": "KING HENRY IV",
"text_entry": "Find we a time for frighted peace to pant,"
}
}
]
}
}
저장된 템플릿이 있고 이를 검증하고 싶다면 render 작업을 사용하세요:
POST /_render/template
{
"id": "play_search_template",
"params": {
"play_name": "Henry IV"
}
}
자세한 내용은 Render Template API를 참고하세요.
검색 템플릿을 사용한 고급 파라미터 변환
Mustache에는 입력 파라미터를 쿼리로 변환하는 다양한 구문 옵션이 있어요. 조건을 지정하거나, 루프를 실행하거나, 배열을 결합하거나, 배열을 JSON으로 변환하는 등의 작업을 할 수 있죠.
조건 (Conditions)
Mustache에서 섹션 태그를 사용해 조건을 나타내요:
{{#var}}var{{/var}}
var가 Boolean 값일 때 이 구문은 if 조건처럼 동작해요. {{#var}}와 {{/var}} 태그는 var가 true로 평가될 때만 그 사이에 있는 값을 삽입해요.
섹션 태그를 그대로 쓰면 JSON이 유효하지 않게 되므로, 쿼리를 문자열 형식으로 작성해야 해요.
다음 명령은 limit 파라미터가 true로 설정된 경우에만 size 파라미터를 쿼리에 포함해요. 다음 예제에서 limit 파라미터는 true이므로 size 파라미터가 활성화돼요. 결과적으로 문서 두 개만 반환받게 돼요.
POST /_render/template
{
"source": "{ {{#limit}} \"size\": \"{{size}}\", {{/limit}} \"query\":{\"match\":{\"play_name\": \"{{play_name}}\"}}}",
"params": {
"play_name": "Henry IV",
"limit": true,
"size": 2
}
}
if-else 조건도 만들 수 있어요. 다음 명령은 limit이 true이면 size를 2로, 그렇지 않으면 size를 10으로 설정해요:
GET /_search/template
{
"source": "{ {{#limit}} \"size\": \"2\", {{/limit}} {{^limit}} \"size\": \"10\", {{/limit}} \"query\":{\"match\":{\"play_name\": \"{{play_name}}\"}}}",
"params": {
"play_name": "Henry IV",
"limit": true
}
}
루프 (Loops)
섹션 태그를 사용해 for-each 루프도 구현할 수 있어요:
{{#var}}{{.}}{{/var}}
var가 배열이면 검색 템플릿이 배열을 반복하며 terms 쿼리를 만들어요.
GET /_search/template
{
"source": "{\"query\":{\"terms\":{\"play_name\":[\"{{#play_name}}\",\"{{.}}\",\"{{/play_name}}\"]}}}",
"params": {
"play_name": [
"Henry IV",
"Othello"
]
}
}
이 템플릿은 다음과 같이 렌더링돼요:
GET _search/template
{
"source": {
"query": {
"terms": {
"play_name": [
"Henry IV",
"Othello"
]
}
}
}
}
결합 (Join)
join 태그를 사용해 배열의 값을(쉼표로 구분해) 연결할 수 있어요:
GET /_search/template
{
"source": {
"query": {
"match": {
"text_entry": "{{#join}}{{text_entry}}{{/join}}"
}
}
},
"params": {
"text_entry": [
"To be",
"or not to be"
]
}
}
다음과 같이 렌더링돼요:
GET _search/template
{
"source": {
"query": {
"match": {
"text_entry": "{0=To be, 1=or not to be}"
}
}
}
}
JSON으로 변환 (Convert to JSON)
toJson 태그를 사용해 파라미터를 JSON 표현으로 변환할 수 있어요:
GET /_search/template
{
"source": "{\"query\":{\"bool\":{\"must\":[{\"terms\": {\"text_entries\": {{#toJson}}text_entries{{/toJson}} }}] }}}",
"params": {
"text_entries": [
{
"term": {
"text_entry": "love"
}
},
{
"term": {
"text_entry": "soldier"
}
}
]
}
}
다음과 같이 렌더링돼요:
GET _search/template
{
"source": {
"query": {
"bool": {
"must": [
{
"terms": {
"text_entries": [
{
"term": {
"text_entry": "love"
}
},
{
"term": {
"text_entry": "soldier"
}
}
]
}
}
]
}
}
}
}
여러 검색 템플릿
msearch 작업을 사용해 여러 검색 템플릿을 묶어 단일 요청으로 OpenSearch 클러스터에 보낼 수 있어요. 이렇게 하면 네트워크 왕복 시간이 절약되므로, 독립적인 요청보다 더 빠르게 응답을 받을 수 있어요.
GET _msearch/template
{"index":"shakespeare"}
{"id":"if_search_template","params":{"play_name":"Henry IV","limit":false,"size":2}}
{"index":"shakespeare"}
{"id":"play_search_template","params":{"play_name":"Henry IV"}}
자세한 내용은 Multi-search Template API를 참고하세요.
검색 템플릿 관리
모든 스크립트를 나열하려면 다음 명령을 실행하세요:
GET /_cluster/state/metadata?pretty&filter_path=**.stored_scripts
특정 검색 템플릿을 검색하려면 다음 명령을 실행하세요:
GET /_scripts/<name_of_search_template>
검색 템플릿을 삭제하려면 다음 명령을 실행하세요:
DELETE /_scripts/<name_of_search_template>
Search template API 작업
다음 검색 템플릿 API 작업을 사용할 수 있어요:
필요한 권한
Security 플러그인을 사용한다면 적절한 권한이 있는지 확인하세요: indices:data/read/search/template.
관련 문서
출처: 문서