Шаблоны поиска
Шаблон поиска — это сохранённый поиск, который можно запускать с различными переменными.
Если вы используете Elasticsearch в качестве бэкэнда поиска, вы можете передавать пользовательский ввод из строки поиска в качестве параметров для шаблона поиска. Это позволяет запускать поиски без необходимости раскрытия синтаксиса запросов Elasticsearch для ваших пользователей.
Если вы используете Elasticsearch для пользовательского приложения, шаблоны поиска позволяют изменять поиски без модификации кода вашего приложения.
Создать шаблон поиска
Для создания или обновления шаблона поиска используйте API для создания или обновления сохранённого скрипта.
Запрос source поддерживает те же параметры, что и тело запроса API поиска.source также принимает переменные Mustache из открытого проекта mustache.java.
Обычно переменные Mustache заключены в двойные фигурные скобки: {{my-var}}. При выполнении запроса с шаблоном Elasticsearch заменяет эти переменные значениями из params. Чтобы узнать больше о синтаксисе Mustache, см. справочник по Mustache.js Шаблоны поиска должны использовать lang типа mustache.
Следующий запрос создаёт шаблон поиска с id типа my-search-template.
resp = client.put_script(
id="my-search-template",
script={
"lang": "mustache",
"source": {
"query": {
"match": {
"message": "{{query_string}}"
}
},
"from": "{{from}}",
"size": "{{size}}"
}
},
)
print(resp) response = client.put_script(
id: 'my-search-template',
body: {
script: {
lang: 'mustache',
source: {
query: {
match: {
message: '{{query_string}}'
}
},
from: '{{from}}',
size: '{{size}}'
}
}
}
)
puts response const response = await client.putScript({
id: "my-search-template",
script: {
lang: "mustache",
source: {
query: {
match: {
message: "{{query_string}}",
},
},
from: "{{from}}",
size: "{{size}}",
},
},
});
console.log(response); PUT _scripts/my-search-template
{
"script": {
"lang": "mustache",
"source": {
"query": {
"match": {
"message": "{{query_string}}"
}
},
"from": "{{from}}",
"size": "{{size}}"
}
}
} Elasticsearch хранит шаблоны поиска в виде скриптов Mustache в состоянии кластера. Elasticsearch компилирует шаблоны поиска в контексте скрипта template. Настройки, которые ограничивают или отключают скрипты, также влияют на шаблоны поиска.
Проверить шаблон поиска
Чтобы протестировать шаблон с разными params, используйте API для рендеринга шаблона поиска.
resp = client.render_search_template(
id="my-search-template",
params={
"query_string": "hello world",
"from": 20,
"size": 10
},
)
print(resp) response = client.render_search_template(
body: {
id: 'my-search-template',
params: {
query_string: 'hello world',
from: 20,
size: 10
}
}
)
puts response const response = await client.renderSearchTemplate({
id: "my-search-template",
params: {
query_string: "hello world",
from: 20,
size: 10,
},
});
console.log(response); POST _render/template
{
"id": "my-search-template",
"params": {
"query_string": "hello world",
"from": 20,
"size": 10
}
} При рендеринге шаблон выводит тело запроса для поиска.
{
"template_output": {
"query": {
"match": {
"message": "hello world"
}
},
"from": "20",
"size": "10"
}
} Вы также можете использовать API для проверки встроенных шаблонов.
resp = client.render_search_template(
source={
"query": {
"match": {
"message": "{{query_string}}"
}
},
"from": "{{from}}",
"size": "{{size}}"
},
params={
"query_string": "hello world",
"from": 20,
"size": 10
},
)
print(resp) response = client.render_search_template(
body: {
source: {
query: {
match: {
message: '{{query_string}}'
}
},
from: '{{from}}',
size: '{{size}}'
},
params: {
query_string: 'hello world',
from: 20,
size: 10
}
}
)
puts response const response = await client.renderSearchTemplate({
source: {
query: {
match: {
message: "{{query_string}}",
},
},
from: "{{from}}",
size: "{{size}}",
},
params: {
query_string: "hello world",
from: 20,
size: 10,
},
});
console.log(response); POST _render/template
{
"source": {
"query": {
"match": {
"message": "{{query_string}}"
}
},
"from": "{{from}}",
"size": "{{size}}"
},
"params": {
"query_string": "hello world",
"from": 20,
"size": 10
}
} Запустить поиск с шаблоном
Чтобы запустить поиск с шаблоном поиска, используйте API шаблонов поиска. Вы можете указывать разные params в каждом запросе.
resp = client.search_template(
index="my-index",
id="my-search-template",
params={
"query_string": "hello world",
"from": 0,
"size": 10
},
)
print(resp) response = client.search_template(
index: 'my-index',
body: {
id: 'my-search-template',
params: {
query_string: 'hello world',
from: 0,
size: 10
}
}
)
puts response const response = await client.searchTemplate({
index: "my-index",
id: "my-search-template",
params: {
query_string: "hello world",
from: 0,
size: 10,
},
});
console.log(response); GET my-index/_search/template
{
"id": "my-search-template",
"params": {
"query_string": "hello world",
"from": 0,
"size": 10
}
} Ответ использует те же свойства, что и ответ API поиска.
{
"took": 36,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"max_score": 0.5753642,
"hits": [
{
"_index": "my-index",
"_id": "1",
"_score": 0.5753642,
"_source": {
"message": "hello world"
}
}
]
}
} Запуск нескольких поисков с шаблонами
Чтобы запустить несколько поисков с шаблонами в одном запросе, используйте API многократного поиска с шаблонами. Эти запросы часто имеют меньшую нагрузку и более высокую скорость, чем несколько отдельных поисков.
resp = client.msearch_template(
index="my-index",
search_templates=[
{},
{
"id": "my-search-template",
"params": {
"query_string": "hello world",
"from": 0,
"size": 10
}
},
{},
{
"id": "my-other-search-template",
"params": {
"query_type": "match_all"
}
}
],
)
print(resp) response = client.msearch_template(
index: 'my-index',
body: [
{},
{
id: 'my-search-template',
params: {
query_string: 'hello world',
from: 0,
size: 10
}
},
{},
{
id: 'my-other-search-template',
params: {
query_type: 'match_all'
}
}
]
)
puts response const response = await client.msearchTemplate({
index: "my-index",
search_templates: [
{},
{
id: "my-search-template",
params: {
query_string: "hello world",
from: 0,
size: 10,
},
},
{},
{
id: "my-other-search-template",
params: {
query_type: "match_all",
},
},
],
});
console.log(response); GET my-index/_msearch/template
{ }
{ "id": "my-search-template", "params": { "query_string": "hello world", "from": 0, "size": 10 }}
{ }
{ "id": "my-other-search-template", "params": { "query_type": "match_all" }} Получить шаблоны поиска
Чтобы получить шаблон поиска, используйте API для получения сохранённого скрипта.
resp = client.get_script(
id="my-search-template",
)
print(resp) response = client.get_script( id: 'my-search-template' ) puts response
const response = await client.getScript({
id: "my-search-template",
});
console.log(response); GET _scripts/my-search-template
Чтобы получить список всех шаблонов поиска и других сохранённых скриптов, используйте API состояния кластера.
resp = client.cluster.state(
metric="metadata",
pretty=True,
filter_path="metadata.stored_scripts",
)
print(resp) response = client.cluster.state( metric: 'metadata', pretty: true, filter_path: 'metadata.stored_scripts' ) puts response
const response = await client.cluster.state({
metric: "metadata",
pretty: "true",
filter_path: "metadata.stored_scripts",
});
console.log(response); GET _cluster/state/metadata?pretty&filter_path=metadata.stored_scripts
Удалить шаблон поиска
Чтобы удалить шаблон поиска, используйте API для удаления сохранённого скрипта.
resp = client.delete_script(
id="my-search-template",
)
print(resp) response = client.delete_script( id: 'my-search-template' ) puts response
const response = await client.deleteScript({
id: "my-search-template",
});
console.log(response); DELETE _scripts/my-search-template
Установить значения по умолчанию
Чтобы установить значение по умолчанию для переменной, используйте следующий синтаксис:
{{my-var}}{{^my-var}}default value{{/my-var}} Если шаблон поиска не указывает значения в своём params, поиск использует значение по умолчанию вместо этого. Например, следующий шаблон устанавливает значения по умолчанию для from и size.
resp = client.render_search_template(
source={
"query": {
"match": {
"message": "{{query_string}}"
}
},
"from": "{{from}}{{^from}}0{{/from}}",
"size": "{{size}}{{^size}}10{{/size}}"
},
params={
"query_string": "hello world"
},
)
print(resp) response = client.render_search_template(
body: {
source: {
query: {
match: {
message: '{{query_string}}'
}
},
from: '{{from}}{{^from}}0{{/from}}',
size: '{{size}}{{^size}}10{{/size}}'
},
params: {
query_string: 'hello world'
}
}
)
puts response const response = await client.renderSearchTemplate({
source: {
query: {
match: {
message: "{{query_string}}",
},
},
from: "{{from}}{{^from}}0{{/from}}",
size: "{{size}}{{^size}}10{{/size}}",
},
params: {
query_string: "hello world",
},
});
console.log(response); POST _render/template
{
"source": {
"query": {
"match": {
"message": "{{query_string}}"
}
},
"from": "{{from}}{{^from}}0{{/from}}",
"size": "{{size}}{{^size}}10{{/size}}"
},
"params": {
"query_string": "hello world"
}
} Кодировать строки в URL
Используйте функцию {{#url}} для кодирования строки в URL.
resp = client.render_search_template(
source={
"query": {
"term": {
"url.full": "{{#url}}{{host}}/{{page}}{{/url}}"
}
}
},
params={
"host": "http://example.com",
"page": "hello-world"
},
)
print(resp) response = client.render_search_template(
body: {
source: {
query: {
term: {
'url.full' => '{{#url}}{{host}}/{{page}}{{/url}}'
}
}
},
params: {
host: 'http://example.com',
page: 'hello-world'
}
}
)
puts response const response = await client.renderSearchTemplate({
source: {
query: {
term: {
"url.full": "{{#url}}{{host}}/{{page}}{{/url}}",
},
},
},
params: {
host: "http://example.com",
page: "hello-world",
},
});
console.log(response); POST _render/template
{
"source": {
"query": {
"term": {
"url.full": "{{#url}}{{host}}/{{page}}{{/url}}"
}
}
},
"params": {
"host": "http://example.com",
"page": "hello-world"
}
} Шаблон рендерится как:
{
"template_output": {
"query": {
"term": {
"url.full": "http%3A%2F%2Fexample.com%2Fhello-world"
}
}
}
} Конкатенация значений
Используйте функцию {{#join}} для конкатенации значений массива в строку, разделённую запятыми. Например, следующий шаблон конкатенирует два адреса электронной почты.
resp = client.render_search_template(
source={
"query": {
"match": {
"user.group.emails": "{{#join}}emails{{/join}}"
}
}
},
params={
"emails": [
"user1@example.com",
"user_one@example.com"
]
},
)
print(resp) response = client.render_search_template(
body: {
source: {
query: {
match: {
'user.group.emails' => '{{#join}}emails{{/join}}'
}
}
},
params: {
emails: [
'user1@example.com',
'user_one@example.com'
]
}
}
)
puts response const response = await client.renderSearchTemplate({
source: {
query: {
match: {
"user.group.emails": "{{#join}}emails{{/join}}",
},
},
},
params: {
emails: ["user1@example.com", "user_one@example.com"],
},
});
console.log(response); POST _render/template
{
"source": {
"query": {
"match": {
"user.group.emails": "{{#join}}emails{{/join}}"
}
}
},
"params": {
"emails": [ "user1@example.com", "user_one@example.com" ]
}
} Шаблон рендерится как:
{
"template_output": {
"query": {
"match": {
"user.group.emails": "user1@example.com,user_one@example.com"
}
}
}
} Вы также можете указать пользовательский разделитель.
resp = client.render_search_template(
source={
"query": {
"range": {
"user.effective.date": {
"gte": "{{date.min}}",
"lte": "{{date.max}}",
"format": "{{#join delimiter='||'}}date.formats{{/join delimiter='||'}}"
}
}
}
},
params={
"date": {
"min": "2098",
"max": "06/05/2099",
"formats": [
"dd/MM/yyyy",
"yyyy"
]
}
},
)
print(resp) response = client.render_search_template(
body: {
source: {
query: {
range: {
'user.effective.date' => {
gte: '{{date.min}}',
lte: '{{date.max}}',
format: "{{#join delimiter='||'}}date.formats{{/join delimiter='||'}}"
}
}
}
},
params: {
date: {
min: '2098',
max: '06/05/2099',
formats: [
'dd/MM/yyyy',
'yyyy'
]
}
}
}
)
puts response const response = await client.renderSearchTemplate({
source: {
query: {
range: {
"user.effective.date": {
gte: "{{date.min}}",
lte: "{{date.max}}",
format:
"{{#join delimiter='||'}}date.formats{{/join delimiter='||'}}",
},
},
},
},
params: {
date: {
min: "2098",
max: "06/05/2099",
formats: ["dd/MM/yyyy", "yyyy"],
},
},
});
console.log(response); POST _render/template
{
"source": {
"query": {
"range": {
"user.effective.date": {
"gte": "{{date.min}}",
"lte": "{{date.max}}",
"format": "{{#join delimiter='||'}}date.formats{{/join delimiter='||'}}"
}
}
}
},
"params": {
"date": {
"min": "2098",
"max": "06/05/2099",
"formats": ["dd/MM/yyyy", "yyyy"]
}
}
} Шаблон рендерится как:
{
"template_output": {
"query": {
"range": {
"user.effective.date": {
"gte": "2098",
"lte": "06/05/2099",
"format": "dd/MM/yyyy||yyyy"
}
}
}
}
} Преобразование в JSON
Используйте функцию {{#toJson}} для преобразования значения переменной в её JSON представление.
Например, следующий шаблон использует {{#toJson}} для передачи массива. Чтобы убедиться, что тело запроса является корректным JSON, source записано в формате строки.
resp = client.render_search_template(
source="{ \"query\": { \"terms\": { \"tags\": {{#toJson}}tags{{/toJson}} }}}",
params={
"tags": [
"prod",
"es01"
]
},
)
print(resp) response = client.render_search_template(
body: {
source: '{ "query": { "terms": { "tags": {{#toJson}}tags{{/toJson}} }}}',
params: {
tags: [
'prod',
'es01'
]
}
}
)
puts response const response = await client.renderSearchTemplate({
source: '{ "query": { "terms": { "tags": {{#toJson}}tags{{/toJson}} }}}',
params: {
tags: ["prod", "es01"],
},
});
console.log(response); POST _render/template
{
"source": "{ \"query\": { \"terms\": { \"tags\": {{#toJson}}tags{{/toJson}} }}}",
"params": {
"tags": [
"prod",
"es01"
]
}
} Шаблон рендерится как:
{
"template_output": {
"query": {
"terms": {
"tags": [
"prod",
"es01"
]
}
}
}
} Вы также можете использовать {{#toJson}} для передачи объектов.
resp = client.render_search_template(
source="{ \"query\": {{#toJson}}my_query{{/toJson}} }",
params={
"my_query": {
"match_all": {}
}
},
)
print(resp) response = client.render_search_template(
body: {
source: '{ "query": {{#toJson}}my_query{{/toJson}} }',
params: {
my_query: {
match_all: {}
}
}
}
)
puts response const response = await client.renderSearchTemplate({
source: '{ "query": {{#toJson}}my_query{{/toJson}} }',
params: {
my_query: {
match_all: {},
},
},
});
console.log(response); POST _render/template
{
"source": "{ \"query\": {{#toJson}}my_query{{/toJson}} }",
"params": {
"my_query": {
"match_all": { }
}
}
} Шаблон рендерится как:
{
"template_output" : {
"query" : {
"match_all" : { }
}
}
} Вы также можете передавать массив объектов.
resp = client.render_search_template(
source="{ \"query\": { \"bool\": { \"must\": {{#toJson}}clauses{{/toJson}} }}}",
params={
"clauses": [
{
"term": {
"user.id": "kimchy"
}
},
{
"term": {
"url.domain": "example.com"
}
}
]
},
)
print(resp) response = client.render_search_template(
body: {
source: '{ "query": { "bool": { "must": {{#toJson}}clauses{{/toJson}} }}}',
params: {
clauses: [
{
term: {
'user.id' => 'kimchy'
}
},
{
term: {
'url.domain' => 'example.com'
}
}
]
}
}
)
puts response const response = await client.renderSearchTemplate({
source: '{ "query": { "bool": { "must": {{#toJson}}clauses{{/toJson}} }}}',
params: {
clauses: [
{
term: {
"user.id": "kimchy",
},
},
{
term: {
"url.domain": "example.com",
},
},
],
},
});
console.log(response); POST _render/template
{
"source": "{ \"query\": { \"bool\": { \"must\": {{#toJson}}clauses{{/toJson}} }}}",
"params": {
"clauses": [
{
"term": {
"user.id": "kimchy"
}
},
{
"term": {
"url.domain": "example.com"
}
}
]
}
} Шаблон рендерится как:
{
"template_output": {
"query": {
"bool": {
"must": [
{
"term": {
"user.id": "kimchy"
}
},
{
"term": {
"url.domain": "example.com"
}
}
]
}
}
}
} Использование условий
Для создания условий if используйте следующий синтаксис:
{{#condition}}content{{/condition}} Если переменная условия равна true, Elasticsearch отображает её содержимое. Например, следующий шаблон ищет данные за прошлый год, если year_scope равно true.
resp = client.render_search_template(
source="{ \"query\": { \"bool\": { \"filter\": [ {{#year_scope}} { \"range\": { \"@timestamp\": { \"gte\": \"now-1y/d\", \"lt\": \"now/d\" } } }, {{/year_scope}} { \"term\": { \"user.id\": \"{{user_id}}\" }}]}}}",
params={
"year_scope": True,
"user_id": "kimchy"
},
)
print(resp) response = client.render_search_template(
body: {
source: '{ "query": { "bool": { "filter": [ {{#year_scope}} { "range": { "@timestamp": { "gte": "now-1y/d", "lt": "now/d" } } }, {{/year_scope}} { "term": { "user.id": "{{user_id}}" }}]}}}',
params: {
year_scope: true,
user_id: 'kimchy'
}
}
)
puts response const response = await client.renderSearchTemplate({
source:
'{ "query": { "bool": { "filter": [ {{#year_scope}} { "range": { "@timestamp": { "gte": "now-1y/d", "lt": "now/d" } } }, {{/year_scope}} { "term": { "user.id": "{{user_id}}" }}]}}}',
params: {
year_scope: true,
user_id: "kimchy",
},
});
console.log(response); POST _render/template
{
"source": "{ \"query\": { \"bool\": { \"filter\": [ {{#year_scope}} { \"range\": { \"@timestamp\": { \"gte\": \"now-1y/d\", \"lt\": \"now/d\" } } }, {{/year_scope}} { \"term\": { \"user.id\": \"{{user_id}}\" }}]}}}",
"params": {
"year_scope": true,
"user_id": "kimchy"
}
} Шаблон отображается как:
{
"template_output" : {
"query" : {
"bool" : {
"filter" : [
{
"range" : {
"@timestamp" : {
"gte" : "now-1y/d",
"lt" : "now/d"
}
}
},
{
"term" : {
"user.id" : "kimchy"
}
}
]
}
}
}
} Если year_scope равно false, шаблон ищет данные за любой период времени.
resp = client.render_search_template(
source="{ \"query\": { \"bool\": { \"filter\": [ {{#year_scope}} { \"range\": { \"@timestamp\": { \"gte\": \"now-1y/d\", \"lt\": \"now/d\" } } }, {{/year_scope}} { \"term\": { \"user.id\": \"{{user_id}}\" }}]}}}",
params={
"year_scope": False,
"user_id": "kimchy"
},
)
print(resp) response = client.render_search_template(
body: {
source: '{ "query": { "bool": { "filter": [ {{#year_scope}} { "range": { "@timestamp": { "gte": "now-1y/d", "lt": "now/d" } } }, {{/year_scope}} { "term": { "user.id": "{{user_id}}" }}]}}}',
params: {
year_scope: false,
user_id: 'kimchy'
}
}
)
puts response const response = await client.renderSearchTemplate({
source:
'{ "query": { "bool": { "filter": [ {{#year_scope}} { "range": { "@timestamp": { "gte": "now-1y/d", "lt": "now/d" } } }, {{/year_scope}} { "term": { "user.id": "{{user_id}}" }}]}}}',
params: {
year_scope: false,
user_id: "kimchy",
},
});
console.log(response); POST _render/template
{
"source": "{ \"query\": { \"bool\": { \"filter\": [ {{#year_scope}} { \"range\": { \"@timestamp\": { \"gte\": \"now-1y/d\", \"lt\": \"now/d\" } } }, {{/year_scope}} { \"term\": { \"user.id\": \"{{user_id}}\" }}]}}}",
"params": {
"year_scope": false,
"user_id": "kimchy"
}
} Шаблон отображается как:
{
"template_output" : {
"query" : {
"bool" : {
"filter" : [
{
"term" : {
"user.id" : "kimchy"
}
}
]
}
}
}
} Для создания условных конструкций if-else используйте следующий синтаксис:
{{#condition}}if content{{/condition}} {{^condition}}else content{{/condition}} Например, следующий шаблон ищет данные за прошлый год, если year_scope равно true. В противном случае, он ищет данные за прошлый день.
resp = client.render_search_template(
source="{ \"query\": { \"bool\": { \"filter\": [ { \"range\": { \"@timestamp\": { \"gte\": {{#year_scope}} \"now-1y/d\" {{/year_scope}} {{^year_scope}} \"now-1d/d\" {{/year_scope}} , \"lt\": \"now/d\" }}}, { \"term\": { \"user.id\": \"{{user_id}}\" }}]}}}",
params={
"year_scope": True,
"user_id": "kimchy"
},
)
print(resp) response = client.render_search_template(
body: {
source: '{ "query": { "bool": { "filter": [ { "range": { "@timestamp": { "gte": {{#year_scope}} "now-1y/d" {{/year_scope}} {{^year_scope}} "now-1d/d" {{/year_scope}} , "lt": "now/d" }}}, { "term": { "user.id": "{{user_id}}" }}]}}}',
params: {
year_scope: true,
user_id: 'kimchy'
}
}
)
puts response const response = await client.renderSearchTemplate({
source:
'{ "query": { "bool": { "filter": [ { "range": { "@timestamp": { "gte": {{#year_scope}} "now-1y/d" {{/year_scope}} {{^year_scope}} "now-1d/d" {{/year_scope}} , "lt": "now/d" }}}, { "term": { "user.id": "{{user_id}}" }}]}}}',
params: {
year_scope: true,
user_id: "kimchy",
},
});
console.log(response); POST _render/template
{
"source": "{ \"query\": { \"bool\": { \"filter\": [ { \"range\": { \"@timestamp\": { \"gte\": {{#year_scope}} \"now-1y/d\" {{/year_scope}} {{^year_scope}} \"now-1d/d\" {{/year_scope}} , \"lt\": \"now/d\" }}}, { \"term\": { \"user.id\": \"{{user_id}}\" }}]}}}",
"params": {
"year_scope": true,
"user_id": "kimchy"
}
} Примеры шаблонов поиска с Mustache
Язык шаблонов Mustache определяет различные типы тегов, которые можно использовать в шаблонах. В следующих разделах описаны некоторые из этих типов тегов и приведены примеры их использования в шаблонах поиска Elasticsearch шаблонов поиска.
Переменные Mustache
Теги Mustache обычно заключены в двойные фигурные скобки. Переменная Mustache: {{my-variable}} является типом тега Mustache. При выполнении запроса с шаблоном Elasticsearch заменяет эти переменные значениями из params.
Например, рассмотрим следующий шаблон поиска:
resp = client.put_script(
id="my-search-template",
script={
"lang": "mustache",
"source": {
"query": {
"match": {
"message": "{{query_string}}"
}
},
"from": "{{from}}",
"size": "{{size}}"
}
},
)
print(resp) response = client.put_script(
id: 'my-search-template',
body: {
script: {
lang: 'mustache',
source: {
query: {
match: {
message: '{{query_string}}'
}
},
from: '{{from}}',
size: '{{size}}'
}
}
}
)
puts response const response = await client.putScript({
id: "my-search-template",
script: {
lang: "mustache",
source: {
query: {
match: {
message: "{{query_string}}",
},
},
from: "{{from}}",
size: "{{size}}",
},
},
});
console.log(response); PUT _scripts/my-search-template
{
"script": {
"lang": "mustache",
"source": {
"query": {
"match": {
"message": "{{query_string}}"
}
},
"from": "{{from}}",
"size": "{{size}}"
}
}
} Проверка вышеуказанного шаблона поиска с params:
resp = client.render_search_template(
id="my-search-template",
params={
"query_string": "hello world",
"from": 20,
"size": 10
},
)
print(resp) response = client.render_search_template(
body: {
id: 'my-search-template',
params: {
query_string: 'hello world',
from: 20,
size: 10
}
}
)
puts response const response = await client.renderSearchTemplate({
id: "my-search-template",
params: {
query_string: "hello world",
from: 20,
size: 10,
},
});
console.log(response); POST _render/template
{
"id": "my-search-template",
"params": {
"query_string": "hello world",
"from": 20,
"size": 10
}
} При рендеринге {{query_string}} в message заменяется на hello world, переданное в params.
{
"template_output": {
"query": {
"match": {
"message": "hello world"
}
},
"from": "20",
"size": "10"
}
} Если шаблон поиска не передает значение вашей query_string, сообщение заменится пустой строкой.
Например:
resp = client.render_search_template(
id="my-search-template",
params={
"from": 20,
"size": 10
},
)
print(resp) response = client.render_search_template(
body: {
id: 'my-search-template',
params: {
from: 20,
size: 10
}
}
)
puts response const response = await client.renderSearchTemplate({
id: "my-search-template",
params: {
from: 20,
size: 10,
},
});
console.log(response); POST _render/template
{
"id": "my-search-template",
"params": {
"from": 20,
"size": 10
}
} При рендеринге шаблон выводится как:
{
"template_output": {
"query": {
"match": {
"message": ""
}
},
"from": "20",
"size": "10"
}
} Разделы
Разделы также являются типом тегов Mustache. Вы можете использовать sections в шаблоне поиска с вложенным или невложенным объектом. Раздел начинается с {{#my-section-variable}} и заканчивается {{/my-section-variable}}.
Следующий шаблон поиска демонстрирует пример использования разделов с вложенными объектами:
resp = client.render_search_template(
source="\n {\n \"query\": {\n \"match\": {\n {{#query_message}}\n {{#query_string}}\n \"message\": \"Hello {{#first_name_section}}{{first_name}}{{/first_name_section}} {{#last_name_section}}{{last_name}}{{/last_name_section}}\"\n {{/query_string}}\n {{/query_message}}\n }\n }\n }\n ",
params={
"query_message": {
"query_string": {
"first_name_section": {
"first_name": "John"
},
"last_name_section": {
"last_name": "kimchy"
}
}
}
},
)
print(resp) response = client.render_search_template(
body: {
source: "\n {\n \"query\": {\n \"match\": {\n {{#query_message}}\n {{#query_string}}\n \"message\": \"Hello {{#first_name_section}}{{first_name}}{{/first_name_section}} {{#last_name_section}}{{last_name}}{{/last_name_section}}\"\n {{/query_string}}\n {{/query_message}}\n }\n }\n }\n ",
params: {
query_message: {
query_string: {
first_name_section: {
first_name: 'John'
},
last_name_section: {
last_name: 'kimchy'
}
}
}
}
}
)
puts response const response = await client.renderSearchTemplate({
source:
'\n {\n "query": {\n "match": {\n {{#query_message}}\n {{#query_string}}\n "message": "Hello {{#first_name_section}}{{first_name}}{{/first_name_section}} {{#last_name_section}}{{last_name}}{{/last_name_section}}"\n {{/query_string}}\n {{/query_message}}\n }\n }\n }\n ',
params: {
query_message: {
query_string: {
first_name_section: {
first_name: "John",
},
last_name_section: {
last_name: "kimchy",
},
},
},
},
});
console.log(response); POST _render/template
{
"source":
"""
{
"query": {
"match": {
{{#query_message}}
{{#query_string}}
"message": "Hello {{#first_name_section}}{{first_name}}{{/first_name_section}} {{#last_name_section}}{{last_name}}{{/last_name_section}}"
{{/query_string}}
{{/query_message}}
}
}
}
""",
"params": {
"query_message": {
"query_string": {
"first_name_section": {"first_name": "John"},
"last_name_section": {"last_name": "kimchy"}
}
}
}
} Шаблон отображается как:
{
"template_output": {
"query": {
"match": {
"message": "Hello John kimchy"
}
}
}
} Списки
Вы можете передать список объектов и перебрать каждый элемент в своем шаблоне поиска.
Например, следующий шаблон поиска объединяет разделы и соответствует всем именам пользователей:
resp = client.put_script(
id="my-search-template",
script={
"lang": "mustache",
"source": {
"query": {
"multi_match": {
"query": "{{query_string}}",
"fields": "[{{#text_fields}}{{user_name}},{{/text_fields}}]"
}
}
}
},
)
print(resp) response = client.put_script(
id: 'my-search-template',
body: {
script: {
lang: 'mustache',
source: {
query: {
multi_match: {
query: '{{query_string}}',
fields: '[{{#text_fields}}{{user_name}},{{/text_fields}}]'
}
}
}
}
}
)
puts response const response = await client.putScript({
id: "my-search-template",
script: {
lang: "mustache",
source: {
query: {
multi_match: {
query: "{{query_string}}",
fields: "[{{#text_fields}}{{user_name}},{{/text_fields}}]",
},
},
},
},
});
console.log(response); PUT _scripts/my-search-template
{
"script": {
"lang": "mustache",
"source": {
"query":{
"multi_match":{
"query": "{{query_string}}",
"fields": """[{{#text_fields}}{{user_name}},{{/text_fields}}]"""
}
}
}
}
} Проверка шаблона:
resp = client.render_search_template(
id="my-search-template",
params={
"query_string": "My string",
"text_fields": [
{
"user_name": "John"
},
{
"user_name": "kimchy"
}
]
},
)
print(resp) response = client.render_search_template(
body: {
id: 'my-search-template',
params: {
query_string: 'My string',
text_fields: [
{
user_name: 'John'
},
{
user_name: 'kimchy'
}
]
}
}
)
puts response const response = await client.renderSearchTemplate({
id: "my-search-template",
params: {
query_string: "My string",
text_fields: [
{
user_name: "John",
},
{
user_name: "kimchy",
},
],
},
});
console.log(response); POST _render/template
{
"id": "my-search-template",
"params": {
"query_string": "My string",
"text_fields": [
{
"user_name": "John"
},
{
"user_name": "kimchy"
}
]
}
} При рендеринге шаблон выводит:
{
"template_output": {
"query": {
"multi_match": {
"query": "My string",
"fields": "[John,kimchy,]"
}
}
}
} Вышеуказанное приведет к проблеме с запятой в конце, что приведет к некорректному JSON. Рабочим решением будет включить инвертированный раздел и добавить переменную, чтобы убедиться, что это последний элемент в массиве.
Например:
resp = client.put_script(
id="my-search-template",
script={
"lang": "mustache",
"source": {
"query": {
"multi_match": {
"query": "{{query_string}}",
"fields": "[{{#text_fields}}{{user_name}}{{^last}},{{/last}}{{/text_fields}}]"
}
}
}
},
)
print(resp) response = client.put_script(
id: 'my-search-template',
body: {
script: {
lang: 'mustache',
source: {
query: {
multi_match: {
query: '{{query_string}}',
fields: '[{{#text_fields}}{{user_name}}{{^last}},{{/last}}{{/text_fields}}]'
}
}
}
}
}
)
puts response const response = await client.putScript({
id: "my-search-template",
script: {
lang: "mustache",
source: {
query: {
multi_match: {
query: "{{query_string}}",
fields:
"[{{#text_fields}}{{user_name}}{{^last}},{{/last}}{{/text_fields}}]",
},
},
},
},
});
console.log(response); PUT _scripts/my-search-template
{
"script": {
"lang": "mustache",
"source": {
"query":{
"multi_match":{
"query": "{{query_string}}",
"fields": """[{{#text_fields}}{{user_name}}{{^last}},{{/last}}{{/text_fields}}]"""
}
}
}
}
} Проверка my-search-template еще раз с переменной: last, чтобы определить, что это последний элемент в массиве:
resp = client.render_search_template(
id="my-search-template",
params={
"query_string": "My string",
"text_fields": [
{
"user_name": "John",
"last": False
},
{
"user_name": "kimchy",
"last": True
}
]
},
)
print(resp) response = client.render_search_template(
body: {
id: 'my-search-template',
params: {
query_string: 'My string',
text_fields: [
{
user_name: 'John',
last: false
},
{
user_name: 'kimchy',
last: true
}
]
}
}
)
puts response const response = await client.renderSearchTemplate({
id: "my-search-template",
params: {
query_string: "My string",
text_fields: [
{
user_name: "John",
last: false,
},
{
user_name: "kimchy",
last: true,
},
],
},
});
console.log(response); POST _render/template
{
"id": "my-search-template",
"params": {
"query_string": "My string",
"text_fields": [
{
"user_name": "John",
"last": false
},
{
"user_name": "kimchy",
"last": true
}
]
}
} При рендеринге шаблон выводит:
{
"template_output": {
"query": {
"multi_match": {
"query": "My string",
"fields": "[John,kimchy]"
}
}
}
} Lambda-функции
Elasticsearch имеет готовые пользовательские функции для поддержки преобразования текста в определенный формат.
Чтобы узнать больше об использовании лямбда-функций Mustache, ознакомьтесь с примерами в Кодирование строк в URL, Конкатенация значений и Преобразование в JSON.
Инвертированные разделы
Инвертированные разделы полезны, когда вам нужно установить значение один раз.
Чтобы использовать инвертированные разделы, используйте следующий синтаксис:
{{^my-variable}} content {{/my-variable}} Например, в следующем шаблоне поиска, если name_exists равно false, message устанавливается со значением Hello World, иначе устанавливается пустая строка.
resp = client.render_search_template(
source={
"query": {
"match": {
"message": "{{^name_exists}}Hello World{{/name_exists}}"
}
}
},
params={
"name_exists": False
},
)
print(resp) response = client.render_search_template(
body: {
source: {
query: {
match: {
message: '{{^name_exists}}Hello World{{/name_exists}}'
}
}
},
params: {
name_exists: false
}
}
)
puts response const response = await client.renderSearchTemplate({
source: {
query: {
match: {
message: "{{^name_exists}}Hello World{{/name_exists}}",
},
},
},
params: {
name_exists: false,
},
});
console.log(response); POST _render/template
{
"source": {
"query": {
"match": {
"message": "{{^name_exists}}Hello World{{/name_exists}}"
}
}
},
"params": {
"name_exists": false
}
} Они также могут быть объединены с условиями и значениями по умолчанию.
Например, в следующем шаблоне поиска, если name_exists равно true, значение {{query_string}} заменяется. Если name_exists равно false, оно устанавливается по умолчанию в World.
resp = client.render_search_template(
source={
"query": {
"match": {
"message": "Hello {{#name_exists}}{{query_string}}{{/name_exists}}{{^name_exists}}World{{/name_exists}}"
}
}
},
params={
"query_string": "Kimchy",
"name_exists": True
},
)
print(resp) response = client.render_search_template(
body: {
source: {
query: {
match: {
message: 'Hello {{#name_exists}}{{query_string}}{{/name_exists}}{{^name_exists}}World{{/name_exists}}'
}
}
},
params: {
query_string: 'Kimchy',
name_exists: true
}
}
)
puts response const response = await client.renderSearchTemplate({
source: {
query: {
match: {
message:
"Hello {{#name_exists}}{{query_string}}{{/name_exists}}{{^name_exists}}World{{/name_exists}}",
},
},
},
params: {
query_string: "Kimchy",
name_exists: true,
},
});
console.log(response); POST _render/template
{
"source": {
"query": {
"match": {
"message": "Hello {{#name_exists}}{{query_string}}{{/name_exists}}{{^name_exists}}World{{/name_exists}}"
}
}
},
"params": {
"query_string": "Kimchy",
"name_exists": true
}
} При рендеринге шаблон выводит:
{
"template_output": {
"query": {
"match": {
"message": "Hello Kimchy"
}
}
}
} Установление разделителя
Вы можете изменить стандартный разделитель: двойные фигурные скобки {{my-variable}} на любой пользовательский разделитель в шаблоне поиска.
Например, следующий шаблон поиска изменяет стандартный разделитель на одиночную круглую скобку (query_string).
resp = client.put_script(
id="my-search-template",
script={
"lang": "mustache",
"source": "\n {\n \"query\": {\n \"match\": {\n {{=( )=}}\n \"message\": \"(query_string)\"\n (={{ }}=)\n }\n }\n }\n "
},
)
print(resp) response = client.put_script(
id: 'my-search-template',
body: {
script: {
lang: 'mustache',
source: "\n {\n \"query\": {\n \"match\": {\n {{=( )=}}\n \"message\": \"(query_string)\"\n (={{ }}=)\n }\n }\n }\n "
}
}
)
puts response const response = await client.putScript({
id: "my-search-template",
script: {
lang: "mustache",
source:
'\n {\n "query": {\n "match": {\n {{=( )=}}\n "message": "(query_string)"\n (={{ }}=)\n }\n }\n }\n ',
},
});
console.log(response); PUT _scripts/my-search-template
{
"script": {
"lang": "mustache",
"source":
"""
{
"query": {
"match": {
{{=( )=}}
"message": "(query_string)"
(={{ }}=)
}
}
}
"""
}
} Тестирование шаблона с новым разделителем:
resp = client.render_search_template(
id="my-search-template",
params={
"query_string": "hello world"
},
)
print(resp) response = client.render_search_template(
body: {
id: 'my-search-template',
params: {
query_string: 'hello world'
}
}
)
puts response const response = await client.renderSearchTemplate({
id: "my-search-template",
params: {
query_string: "hello world",
},
});
console.log(response); POST _render/template
{
"id": "my-search-template",
"params": {
"query_string": "hello world"
}
} При рендеринге шаблон выводит:
{
"template_output": {
"query": {
"match": {
"message": "hello world"
}
}
}
} Неподдерживаемые возможности
Следующие возможности Mustache не поддерживаются в шаблонах поиска Elasticsearch:
- Частичные
© 2023-2025 Elasticsearch
As of September 2024, Elasticsearch is available under a choice of three licenses: the Server Side Public License (SSPL), the Elastic License, or the AGPLv3 (OSI approved).
Elasticsearch and the Elasticsearch logo are trademarks of Elasticsearch B.V., registered in the U.S. and in other countries.
https://www.elastic.co/guide/en/elasticsearch/reference/8.17/search-template.html