腳本化 field 示例
本小節展示了 Kibana 中一些常見場景下的 Lucene expressions 和 Painless 腳本化 field 示例。如上所述,這些示例以來自 Kibana 入門教程的數據集爲基礎,並且假定你使用的是 Elasticsearch 和 Kibana 5.1.1,因爲在之前的版本中,某些類型的腳本化 field 中存在一些與過濾和排序相關的已知問題。
由於 Elasticsearch 5.0 默認啓用 Lucene expressions 和 Painless,因此腳本化 fields 在大部分情況下應該都能夠開箱即用。唯一例外的是那些需要對 fields 進行基於正則表達式的解析的腳本,這些腳本需要你在 elasticsearch.yml中設置下面的設置,爲 Painless 打開正則表達式匹配:
script.painless.regex.enabled: true
對單個 field 執行計算
示例:由字節計算出千字節
語言:expressions
返回類型:數字
doc['bytes'].value / 1024
注意:切記 Kibana 腳本化 fields 一次只能處理一個單獨的文檔,因此無法在腳本化 fields 中進行時間序列運算。
返回數字的日期運算
示例:將日期解析成小時時間
語言:expressions
返回類型:數字
Lucene expressions 提供了大量開箱即用的 日期處理函數。但是,由於 Lucene expressions 只能返回數字值,因此我們必須使用 Painless 來返回基於字符串的星期值(如下所示)。
doc['@timestamp'].date.hourOfDay
注意:上面的腳本將返回 1-24
doc['@timestamp'].date.dayOfWeek
注意:上面的腳本將返回 1-7
合併兩個字符串值
示例:合併源和目標或名字和姓氏
語言:painless
返回類型:字符串
doc['geo.dest.keyword'].value + ':' + doc['geo.src.keyword'].value
注意:由於腳本化 field 需要操作doc_values中的 field,因此我們上面使用的是 .keyword 版本的字符串。
引入邏輯運算
示例:爲所有超過 10000 字節的文檔返回標籤“big download”
語言:painless
返回類型:字符串
if (doc['bytes'].value > 10000) {
return "big download";
}
return "";
注意:引入邏輯運算時,確保每個執行路徑都具有良好定義的返回語句和良好定義的返回值(而非 null)。例如,在 Kibana 過濾器中使用上述腳本化 field 時,如果最後沒有返回語句或者語句返回 null,都會出現編譯錯誤。另外還請注意,Kibana 腳本化 field 中不支持將邏輯運算分解成函數。
返回子串
示例:返回 URL 中最後一個斜線後面的部分
語言:painless
返回類型:字符串
def path = doc['url.keyword'].value;
if (path != null) {
int lastSlashIndex = path.lastIndexOf('/');
if (lastSlashIndex > 0) {
return path.substring(lastSlashIndex+1);
}
}
return "";
注意:儘量避免使用正則表達式提取子串,因爲 indexOf() 操作佔用的資源更少,更不易出錯。
使用正則表達式匹配字符串,並對匹配進行操作
示例:如果在 field“referer”中找到子串“error”,則返回字符串“error”,否則返回字符串“no error”。
語言:painless
返回類型:字符串
if (doc['referer.keyword'].value =~ /error/) {
return "error"
} else {
return "no error"
}
注意:簡化的正則表達式語法對基於正則表達式匹配的條件句有用。
匹配字符串並返回該匹配
示例:返回域,即 field “host”中最後一個點後面的字符串。
語言:painless
返回類型:字符串
def m = /^.*\.([a-z]+)$/.matcher(doc['host.keyword'].value);
if ( m.matches() ) {
return m.group(1)
} else {
return "no match"
}
注意:通過正則表達式 matcher() 函數定義對象,可以提取與正則表達式相匹配的字符組並將它們返回。
匹配數字並返回該匹配
示例:返回 IP 地址的第一個八位組(存儲爲字符串)並將它視爲一個數字。
語言:painless
返回類型:數字
def m = /^([0-9]+)\..*$/.matcher(doc['clientip.keyword'].value);
if ( m.matches() ) {
return Integer.parseInt(m.group(1))
} else {
return 0
}
注意:在腳本中返回正確的數據類型是很重要的。正則表達式匹配返回的是字符串,即便匹配的是數字依然返回字符串,因此返回時應該顯式地將它轉換成整數。
返回字符串的日期運算
示例:將日期解析成星期值再解析成字符串
語言:painless
返回類型:字符串
LocalDateTime.ofInstant(Instant.ofEpochMilli(doc['@timestamp'].value), ZoneId.of('Z')).getDayOfWeek().getDisplayName(TextStyle.FULL, Locale.getDefault())
注意:由於 Painless 支持 Java 所有的原生類型,因此通過它可以獲取與這些類型相關的原生函數,例如 LocalDateTime(),這在執行更加高級的日期運算時有用。