Определение полей выполнения в запросе поиска
Вы можете указать раздел runtime_mappings в запросе поиска, чтобы создать поля выполнения, которые существуют только в рамках запроса. Вы указываете скрипт в рамках раздела runtime_mappings, так же, как и при добавлении поля выполнения в отображение.
Определение поля выполнения в запросе поиска использует тот же формат, что и определение поля выполнения в отображении индекса. Просто скопируйте определение поля из раздела runtime в отображении индекса в раздел runtime_mappings запроса поиска.
Следующий запрос поиска добавляет поле day_of_week в раздел runtime_mappings. Значения поля будут вычисляться динамически и только в контексте этого запроса поиска:
resp = client.search(
index="my-index-000001",
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"
}
}
},
)
print(resp) const response = await client.search({
index: "my-index-000001",
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",
},
},
},
});
console.log(response); 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"
}
}
}
} Создание полей выполнения, использующих другие поля выполнения
Вы даже можете определять поля выполнения в запросе поиска, которые возвращают значения из других полей выполнения. Например, предположим, что вы массово индексируете данные датчиков:
resp = client.bulk(
index="my-index-000001",
refresh=True,
operations=[
{
"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"
}
}
],
)
print(resp) response = client.bulk(
index: 'my-index-000001',
refresh: true,
body: [
{
index: {}
},
{
"@timestamp": 1_516_729_294_000,
model_number: 'QVKC92Q',
measures: {
voltage: '5.2',
start: '300',
end: '8675309'
}
},
{
index: {}
},
{
"@timestamp": 1_516_642_894_000,
model_number: 'QVKC92Q',
measures: {
voltage: '5.8',
start: '300',
end: '8675309'
}
},
{
index: {}
},
{
"@timestamp": 1_516_556_494_000,
model_number: 'QVKC92Q',
measures: {
voltage: '5.1',
start: '300',
end: '8675309'
}
},
{
index: {}
},
{
"@timestamp": 1_516_470_094_000,
model_number: 'QVKC92Q',
measures: {
voltage: '5.6',
start: '300',
end: '8675309'
}
},
{
index: {}
},
{
"@timestamp": 1_516_383_694_000,
model_number: 'HG537PU',
measures: {
voltage: '4.2',
start: '400',
end: '8625309'
}
},
{
index: {}
},
{
"@timestamp": 1_516_297_294_000,
model_number: 'HG537PU',
measures: {
voltage: '4.0',
start: '400',
end: '8625309'
}
}
]
)
puts response const response = await client.bulk({
index: "my-index-000001",
refresh: "true",
operations: [
{
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",
},
},
],
});
console.log(response); 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.start и measures.end, но агрегирование не удаётся, потому что нельзя агрегировать по полям типа text. На помощь приходят поля выполнения! Вы можете добавить поля выполнения с теми же именами, что и ваши индексированные поля, и изменить тип данных:
resp = client.indices.put_mapping(
index="my-index-000001",
runtime={
"measures.start": {
"type": "long"
},
"measures.end": {
"type": "long"
}
},
)
print(resp) response = client.indices.put_mapping(
index: 'my-index-000001',
body: {
runtime: {
'measures.start' => {
type: 'long'
},
'measures.end' => {
type: 'long'
}
}
}
)
puts response const response = await client.indices.putMapping({
index: "my-index-000001",
runtime: {
"measures.start": {
type: "long",
},
"measures.end": {
type: "long",
},
},
});
console.log(response); PUT my-index-000001/_mapping
{
"runtime": {
"measures.start": {
"type": "long"
},
"measures.end": {
"type": "long"
}
}
} Поля выполнения имеют приоритет над полями, определёнными с тем же именем в отображениях индексов. Эта гибкость позволяет вам затенять существующие поля и вычислять другое значение без изменения самого поля. Если вы допустили ошибку в отображении индекса, вы можете использовать поля выполнения для вычисления значений, которые переопределяют значения в отображении во время запроса поиска.
Теперь вы можете легко выполнить агрегирование по среднему значению (average aggregation) по полям measures.start и measures.end:
resp = client.search(
index="my-index-000001",
aggs={
"avg_start": {
"avg": {
"field": "measures.start"
}
},
"avg_end": {
"avg": {
"field": "measures.end"
}
}
},
)
print(resp) response = client.search(
index: 'my-index-000001',
body: {
aggregations: {
avg_start: {
avg: {
field: 'measures.start'
}
},
avg_end: {
avg: {
field: 'measures.end'
}
}
}
}
)
puts response const response = await client.search({
index: "my-index-000001",
aggs: {
avg_start: {
avg: {
field: "measures.start",
},
},
avg_end: {
avg: {
field: "measures.end",
},
},
},
});
console.log(response); 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
}
}
} Кроме того, вы можете определить поле выполнения в запросе поиска, которое вычисляет значение, а затем выполнить агрегирование по статистике (stats aggregation) по этому полю в том же запросе.
Поле выполнения duration не существует в отображении индекса, но мы всё ещё можем выполнить поиск и агрегирование по этому полю. Следующий запрос возвращает вычисленное значение для поля duration и выполняет агрегирование по статистике для вычисления статистических данных над числовыми значениями, извлечёнными из агрегированных документов.
resp = client.search(
index="my-index-000001",
runtime_mappings={
"duration": {
"type": "long",
"script": {
"source": "\n emit(doc['measures.end'].value - doc['measures.start'].value);\n "
}
}
},
aggs={
"duration_stats": {
"stats": {
"field": "duration"
}
}
},
)
print(resp) response = client.search(
index: 'my-index-000001',
body: {
runtime_mappings: {
duration: {
type: 'long',
script: {
source: "\n emit(doc['measures.end'].value - doc['measures.start'].value);\n "
}
}
},
aggregations: {
duration_stats: {
stats: {
field: 'duration'
}
}
}
}
)
puts response const response = await client.search({
index: "my-index-000001",
runtime_mappings: {
duration: {
type: "long",
script: {
source:
"\n emit(doc['measures.end'].value - doc['measures.start'].value);\n ",
},
},
},
aggs: {
duration_stats: {
stats: {
field: "duration",
},
},
},
});
console.log(response); 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
}
}
}
© 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/runtime-search-request.html