本篇文章給大家分享的是有關Kuiper中如何使用Golang模版template定制分析結果,小編覺得挺實用的,因此分享給大家學習,希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。
10年積累的成都網(wǎng)站制作、成都做網(wǎng)站、外貿營銷網(wǎng)站建設經(jīng)驗,可以快速應對客戶對網(wǎng)站的新想法和需求。提供各種問題對應的解決方案。讓選擇我們的客戶得到更好、更有力的網(wǎng)絡服務。我雖然不認識你,你也不認識我。但先網(wǎng)站設計后付款的網(wǎng)站建設流程,更有津南免費網(wǎng)站建設讓你可以放心的選擇與我們合作。
用戶通過 Kuiper 進行數(shù)據(jù)分析處理后,使用各種 sink 可以往不同的系統(tǒng)發(fā)送數(shù)據(jù)分析結果。針對同樣的分析結果,不同的 sink 需要的格式可能未必一樣。比如,在某物聯(lián)網(wǎng)場景中,當發(fā)現(xiàn)某設備溫度過高的時候,需要向云端某 rest 服務發(fā)送一個請求,同時在本地需要通過 MQTT 協(xié)議 往設備發(fā)送一個控制命令,這兩者需要的數(shù)據(jù)格式可能并不一樣,因此,需要對來自于分析的結果進行「二次處理」后,才可以往不同的目標發(fā)送針對數(shù)據(jù)。下面將介紹如何利用 sink 中的數(shù)據(jù)模版(data template )來實現(xiàn)對分析結果的「二次處理」。
Golang 模版將一段邏輯應用到數(shù)據(jù)上,然后按照用戶指定的邏輯對數(shù)據(jù)進行格式化輸出,Golang 模版常見的使用場景為在網(wǎng)頁開發(fā)中,比如將 Golang 中的某數(shù)據(jù)結構進行轉換和控制后,將其轉換為 HTML 標簽輸出到瀏覽器。在Kuiper 使用了 Golang 的 template(模版)對分析結果實現(xiàn)「二次處理」,請參考以下來自于 Golang 的官方介紹。
模版是通過將其應用到一個數(shù)據(jù)結構上來執(zhí)行的。模版中的注釋 (Annotations) 指的是數(shù)據(jù)結構中的元素(典型的為結構體中的一個字段,或者 map 中的一個 key),注釋用于控制執(zhí)行、并獲取用于顯示的值。模版的執(zhí)行會迭代數(shù)據(jù)結構并設置游標,通過符號「.」 來表示,稱之為「dot」,在執(zhí)行過程中指向數(shù)據(jù)結構中的當前位置。
模版的輸入文本可以為 UTF-8 編碼的任意文本。「
動作
(Actions)」 -- 數(shù)據(jù)求值或者控制結構 - 是通過 "{{" 和 "}}" 來界定的;所有在動作
之外的文本會被保持原樣到輸出,除了 raw strings,動作
不可跨行(注釋除外)。
Golang 模版提供了一些內置的動作,可以讓用戶寫各種控制語句,用于提取內容。比如,
根據(jù)判斷條件來輸出不同的內容
{{if pipeline}} T1 {{else}} T0 {{end}}
循環(huán)遍歷數(shù)據(jù),并進行處理
{{range pipeline}} T1 {{else}} T0 {{end}}
讀者可以看到,動作是用 {{}}
界定的,在 Kuiper 的數(shù)據(jù)模版使用過程中,由于輸出一般也是 JSON 格式, 而 JSON 格式是用 {}
來界定,因此讀者在不太熟悉使用的時候,在使用 Kuiper 的數(shù)據(jù)模版的功能會覺得比較難以理解。比如以下的例子中,
{{if pipeline}} {"field1": true} {{else}} {"field1": false} {{end}}
上述表達式的意思如下(請注意動作的界定符和 JSON 的界定符):
如果滿足了條件 pipeline,則輸出 JSON 字符串 {"field1": true}
否則輸出 JSON 字符串 {"field1": false}
Golang 的模版可以作用于各種數(shù)據(jù)結構,比如 map、切片 (slice),通道等,而 Kuiper 的 sink 中的數(shù)據(jù)模版得到的數(shù)據(jù)類型是固定的,是一個包含了 Golang map
切片的數(shù)據(jù)類型,如下所示。
[]map[string]interface{}
流入 sink 的數(shù)據(jù)是一個 map[string]interface{}
切片的數(shù)據(jù)結構,但是用戶往目標 sink 發(fā)送數(shù)據(jù)的時候,可能是需要單條的數(shù)據(jù),而不是所有的數(shù)據(jù)。比如在這篇 Kuiper 與 AWS IoT Hub 集成 的文章中所介紹的,規(guī)則產(chǎn)生的樣例數(shù)據(jù)如下所示。
[ {"device_id":"1","t_av":36.25,"t_count":4,"t_max":80,"t_min":10}, {"device_id":"2","t_av":27,"t_count":4,"t_max":45,"t_min":12} ]
在發(fā)送到 sink 的時候,希望每條數(shù)據(jù)分開發(fā)送,首先需要將 sink 的 sendSingle
設置為 true
,然后使用數(shù)據(jù)模版:{{json .}}
,完整配置如下,用戶可以將其拷貝到某 sink 配置的最后。
... "sendSingle": true, "dataTemplate": "{{json .}}"
將 sendSingle
設置為 true
后,Kuiper 把傳遞給 sink 的 []map[string]interface{}
數(shù)據(jù)類型進行遍歷處理,對于遍歷過程中的每一條數(shù)據(jù)都會應用用戶指定的數(shù)據(jù)模版
json
是 Kuiper 提供的函數(shù)(用戶可以參考 Kuiper 擴展模版函數(shù)來了解更多的 Kuiper 擴展),可以將傳入的參數(shù)轉化為 JSON 字符串輸出,對于遍歷到的每一條數(shù)據(jù),將 map 中的內容轉換為 JSON 字符串
Golang 還內置提供了一些函數(shù),用戶可以參考更多 Golang 內置提供的函數(shù)來獲取更多函數(shù)信息。
還是針對上述例子,需要對返回的 t_av
(平均溫度)做一些轉換,轉換的基本要求就是根據(jù)不同的平均溫度,加入不同的描述文字,用于目標 sink 中的處理。規(guī)則如下,
當溫度小于 30,描述字段為「Current temperature is$t_av
, it's normal.」
當溫度大于 30,描述字段為「Current temperature is$t_av
, it's high.」
假設目標 sink 還是需要 JSON 數(shù)據(jù),該數(shù)據(jù)模版的內容如下,
... "dataTemplate": "{\"device_id\": {{.device_id}}, \"description\": \"{{if lt .t_av 30.0}}Current temperature is {{.t_av}}, it's normal.\"{{else if ge .t_av 30.0}}Current temperature is {{.t_av}}, it's high.\"{{end}}}" "sendSingle": true,
在上述的數(shù)據(jù)模版中,使用了 {{if pipeline}} T1 {{else if pipeline}} T0 {{end}}
的內置動作,看上去比較復雜,稍微調整一下,去掉轉義并加入縮進后排版如下(注意:在生成 Kuiper 規(guī)則的時候,不能傳入以下優(yōu)化后排版的規(guī)則)。
{"device_id": {{.device_id}}, "description": " {{if lt .t_av 30.0}} Current temperature is {{.t_av}}, it's normal." {{else if ge .t_av 30.0}} Current temperature is {{.t_av}}, it's high." {{end}} }
使用了 Golang 內置的二元比較函數(shù),
lt
: 小于
ge
:大于等于
值得注意的是,在 lt
和 ge
函數(shù)中,第二個參數(shù)值的類型應該與 map 中的數(shù)據(jù)實際的數(shù)據(jù)類型一致,否則會出錯。如在上述的例子中,溫度大于 30
的情況,因為 map 中實際平均數(shù)的類型為 float,因此第二個參數(shù)的值需傳入 30.0
,而不是 30
。
另外,模版還是應用到切片中每條記錄上,所以還是需要將 sendSingle
屬性設置為 true
。最終該數(shù)據(jù)模版針對上述數(shù)據(jù)產(chǎn)生的內容如下,
{"device_id": 1, "description": "Current temperature is 36.25, it's high."} {"device_id": 2, "description": "Current temperature is 27, it's normal."}
通過給 sink 的 sendSingle
屬性設置為 true
,可以實現(xiàn)把傳遞給 sink 的切片數(shù)據(jù)進行遍歷。在此處,我們將介紹一些更為復雜的例子,比如在 sink 的結果中,包含了嵌套的數(shù)組類型的數(shù)據(jù),如何通過在數(shù)據(jù)模版中提供的遍歷功能,自己來實現(xiàn)遍歷。
假設流入 sink 中的數(shù)據(jù)內容如下所示,
{"device_id":"1", "values": [ {"temperature": 10.5}, {"temperature": 20.3}, {"temperature": 30.3} ] }
需求為,
當發(fā)現(xiàn) "values" 數(shù)組中某個 temperature
值小于等于 25
的時候,增加一個名為 description
的屬性,將其值設置為 fine
。
當發(fā)現(xiàn) "values" 數(shù)組中某個 temperature
值大于 25
的時候,增加一個名為 description
的屬性,將其值設置為 high
。
"sendSingle": true, "dataTemplate": "{{$len := len .values}} {{$loopsize := add $len -1}} {\"device_id\": \"{{.device_id}}\", \"description\": [{{range $index, $ele := .values}} {{if le .temperature 25.0}}\"fine\"{{else if gt .temperature 25.0}}\"high\"{{end}} {{if eq $loopsize $index}}]{{else}},{{end}}{{end}}}"
該數(shù)據(jù)模板比較復雜,解釋如下,
{{$len := len .values}} {{$loopsize := add $len -1}}
,這一段執(zhí)行了兩個表達式,第一個 len
函數(shù)取得數(shù)據(jù)中 values
的長度,第二個 add
將其值減 1 并賦值到變量 loopsize
:由于 Golang 的表達式中目前還不支持直接將數(shù)值減 1 的操作, add
是 Kuiper 為實現(xiàn)該功能而擴展的函數(shù)。
{\"device_id\": \"{{.device_id}}\", \"description\": [
這一段模版在作用到樣例數(shù)據(jù)后,生成了 JSON 串 {"device_id": "1", "description": [
{{range $index, $ele := .values}} {{if le .temperature 25.0}}\"fine\"{{else if gt .temperature 25.0}}\"high\"{{end}} {{if eq $loopsize $index}}]{{else}},{{end}}{{end}}
,這一段模版看起來比較復雜,但是如果把它調整一下,去掉轉義并加入縮進后排版如下,看起來可能會更加清晰(注意:在生成 Kuiper 規(guī)則的時候,不能傳入以下優(yōu)化后排版的規(guī)則)。
{{range $index, $ele := .values}} {{if le .temperature 25.0}} "fine" {{else if gt .temperature 25.0}} "high" {{end}} {{if eq $loopsize $index}} ] {{else}} , {{end}} {{end}}
第一個條件判斷生成是 fine
或者 high
;第二個條件判斷是生成分隔數(shù)組的 ,
還是數(shù)組結尾的 ]
。
另外,模版還是應用到切片中每條記錄上,所以還是需要將 sendSingle
屬性設置為 true
。最終該數(shù)據(jù)模版針對上述數(shù)據(jù)產(chǎn)生的內容如下,
{"device_id": "1", "description": [ "fine" , "fine" , "high" ]}
通過 Kuiper 提供的數(shù)據(jù)模版功能可以實現(xiàn)對分析結果的二次處理,以滿足不同的 sink 目標的需求。但是讀者也可以看到,由于 Golang 模版本身的限制,實現(xiàn)比較復雜的數(shù)據(jù)轉換的時候會比較笨拙,希望將來 Golang 模版的功能可以做得更加強大和靈活,這樣可以支持處理更加復雜的需求。目前建議用戶可以通過數(shù)據(jù)模版來實現(xiàn)一些較為簡單的數(shù)據(jù)的轉換;如果用戶需要對數(shù)據(jù)進行比較復雜的處理,并且自己擴展了 sink 的情況下,可以在 sink 的實現(xiàn)中直接進行處理。
另外,Kuiper 團隊在規(guī)劃將來支持自定義擴展 sink 中的模版函數(shù),這樣一些比較復雜的邏輯可以在函數(shù)內部實現(xiàn),用戶調用的時候只需一個簡單的模版函數(shù)調用即可實現(xiàn)。
以上就是Kuiper中如何使用Golang模版template定制分析結果,小編相信有部分知識點可能是我們日常工作會見到或用到的。希望你能通過這篇文章學到更多知識。更多詳情敬請關注創(chuàng)新互聯(lián)行業(yè)資訊頻道。