在我們使用es
的開發過程中可能會遇到這麼一種情況,比如我們的線路名稱欄位lineName
欄位在設定mapping
的時候使用的是text
型別,但是後期發現需要使用這個欄位來進行聚合操作
,那麼我們除了對索引進行reindex
操作外,還有什麼辦法可以解決這個問題呢?此處我們通過runtime field
來解決。
執行時欄位是在查詢時評估的欄位。是在es7.11之後增加的
執行時欄位使您能夠:
查詢
,排序
,聚合
等操作。fields
中和_source
中可以返回同名的欄位,但是值可能不一樣。_source
中,需要通過fields api
來獲取。PUT /index_script_fields
{
"mappings": {
"runtime": {
"aggLineName": {
"type": "keyword",
"script": {
"source": "emit(doc['lineName'].value)"
}
}
},
"properties": {
"lineId": {
"type": "keyword"
},
"lineName": {
"type": "text"
}
}
}
}
POST /index_script_fields/_mapping
{
"runtime": {
"aggLineName": {
"type": "keyword",
"script": {
"source": "emit(doc['lineName'].value)"
}
}
}
}
POST /index_script_fields/_mapping
{
"runtime": {
"aggLineName": null
}
}
GET /index_script_fields/_search
{
"runtime_mappings": {
"lineName": {
"type": "keyword",
"script": "emit(params['_source']['lineName']+'new')"
}
},
"query": {
"match_all": {}
},
"fields": [
"lineName"
]
}
我們存在一個線路mapping,其中lineName
在設計的使用使用了text
型別,現在我們需要根據這個欄位來進行聚合操作,那麼使用runtime field
該如何操作呢?
PUT /index_script_fields
{
"mappings": {
"properties": {
"lineId": {
"type": "keyword"
},
"lineName": {
"type": "text"
}
}
}
}
注意此時的lineName
的型別是text
PUT /index_script_fields/_bulk
{"index":{"_id":1}}
{"lineId":"line-01","lineName":"線路A"}
{"index":{"_id":2}}
{"lineId":"line-01","lineName":"線路A"}
{"index":{"_id":3}}
{"lineId":"line-02","lineName":"線路C"}
從上方的mapping
中可以lineName
是text
型別,是不可進行聚合操作的,那麼此時我們想進行聚合操作,就可以使用runtime field
來實現。
GET /index_script_fields/_search
{
"runtime_mappings": {
"aggLineName": {
"type": "keyword",
"script": "emit(params['_source']['lineName']+'new')"
}
},
"query": {
"match_all": {}
},
"fields": [
"lineName"
],
"aggs": {
"agg_line_name": {
"terms": {
"field": "aggLineName",
"size": 10
}
}
}
}
@Test
@DisplayName("lineName欄位是text型別,無法進行聚合操作,定義一個runtime field來進行聚合操作")
public void test01() throws IOException {
SearchRequest request = SearchRequest.of(searchRequest ->
searchRequest.index(INDEX_NAME)
// 查詢所有資料
.query(query -> query.matchAll(matchAll -> matchAll))
// runtime field欄位不會出現在 _source中,需要使用使用 fields api來獲取
.fields(fields -> fields.field("lineName"))
// 建立一個 runtime filed 欄位型別是 keyword
.runtimeMappings("aggLineName", runtime ->
runtime
// 此處給欄位型別為keyword
.type(RuntimeFieldType.Keyword)
.script(script ->
script.inline(inline ->
// runtime field中如果使用 painless指令碼語言,需要使用emit
inline.lang(ScriptLanguage.Painless)
.source("emit(params['_source']['lineName']+'new')")
)
)
)
// 進行聚合操作
.aggregations("agg_line_name", agg ->
// 此處的 aggLineName即為上一步runtime field的欄位
agg.terms(terms -> terms.field("aggLineName").size(10))
)
.size(100)
);
System.out.println("request: " + request);
SearchResponse<Object> response = client.search(request, Object.class);
System.out.println("response: " + response);
1、https://www.elastic.co/guide/en/elasticsearch/reference/8.6/runtime.html
本文來自部落格園,作者:huan1993,轉載請註明原文連結:https://www.cnblogs.com/huan1993/p/17084355.html