使用 JavaScript 腳本來(lái)進(jìn)行復(fù)雜的查詢改寫
有這么一個(gè)需求:
網(wǎng)關(guān)里怎樣對(duì)跨集群搜索進(jìn)行支持的呢?我想實(shí)現(xiàn): 輸入的搜索請(qǐng)求是?
lp:9200/index1/_search
?這個(gè)索引在 3 個(gè)集群上,需要跨集群檢索,也就是網(wǎng)關(guān)能否改成?lp:9200/cluster01:index1,cluster02,index1,cluster03:index1/_search
?呢? 索引有一百多個(gè),名稱不一定是 app, 還可能多個(gè)索引一起的。
極限網(wǎng)關(guān)自帶的過(guò)濾器?content_regex_replace
?雖然可以實(shí)現(xiàn)字符正則替換,但是這個(gè)需求是帶參數(shù)的變量替換,稍微復(fù)雜一點(diǎn),沒有辦法直接用這個(gè)正則替換實(shí)現(xiàn),有什么其他辦法實(shí)現(xiàn)么?
使用腳本過(guò)濾器?#
當(dāng)然有的,上面的這個(gè)需求,理論上我們只需要將其中的索引?index1
?匹配之后,替換為?cluster01:index1,cluster02,index1,cluster03:index1
?就行了。
答案就是使用自定義腳本來(lái)做,再?gòu)?fù)雜的業(yè)務(wù)邏輯都不是問(wèn)題,都能通過(guò)自定義腳本來(lái)實(shí)現(xiàn),一行腳本不行,那就兩行。
使用極限網(wǎng)關(guān)提供的?JavaScript?過(guò)濾器可以很靈活的實(shí)現(xiàn)這個(gè)功能,具體繼續(xù)看。
定義腳本?#
首先創(chuàng)建一個(gè)腳本文件,放在網(wǎng)關(guān)數(shù)據(jù)目錄的?scripts
?子目錄下面,如下:
這個(gè)腳本的內(nèi)容如下:
和普通的 JavaScript 一樣,定義一個(gè)特定的函數(shù)?process
?來(lái)處理請(qǐng)求里面的上下文信息,_ctx.request.path
?是網(wǎng)關(guān)內(nèi)置上下文的一個(gè)變量,用來(lái)獲取請(qǐng)求的路徑,通過(guò)?context.Get("_ctx.request.path")
?在腳本里面進(jìn)行訪問(wèn)。
中間我們使用了 JavaScript 的正則匹配和字符處理,做了一些字符拼接,得到新的路徑?newPath
?變量,最后使用?context.Put("_ctx.request.path",newPath)
?更新網(wǎng)關(guān)請(qǐng)求的路徑信息,從而實(shí)現(xiàn)查詢條件里面的參數(shù)替換。
有關(guān)網(wǎng)關(guān)內(nèi)置上下文的變量列表,請(qǐng)?jiān)L問(wèn)?Request Context
定義網(wǎng)關(guān)?#
接下來(lái),創(chuàng)建一個(gè)網(wǎng)關(guān)配置,并使用?javascript
?過(guò)濾器調(diào)用該腳本,如下:
上面的例子中,使用了一個(gè)?javascript
?過(guò)濾器,并且指定了加載的腳本文件為?index_path_rewrite.js
,并使用了兩個(gè)?dump
?過(guò)濾器來(lái)輸出腳本運(yùn)行前后的路徑信息,最后再使用一個(gè)?elasticsearch
?過(guò)濾器來(lái)轉(zhuǎn)發(fā)請(qǐng)求給 Elasticsearch 進(jìn)行查詢。
啟動(dòng)網(wǎng)關(guān)?#
我們啟動(dòng)網(wǎng)關(guān)測(cè)試一下,如下:
執(zhí)行測(cè)試?#
運(yùn)行下面的查詢來(lái)驗(yàn)證查詢結(jié)果,如下:
可以看到網(wǎng)關(guān)通過(guò)?dump
?過(guò)濾器輸出的調(diào)試信息:
查詢條件按照我們的需求進(jìn)行了改寫,Nice!
重寫 DSL 查詢語(yǔ)句?#
好吧,我們剛剛只是修改了查詢的索引而已,那么查詢請(qǐng)求的 DSL 呢?行不行?
那自然是可以的嘛,瞧下面的例子:
先是獲取查詢請(qǐng)求,然后轉(zhuǎn)換成 JSON 對(duì)象,之后任意修改查詢對(duì)象就行了,保存回去,搞掂。
測(cè)試一下:
輸出:
是不是感覺解鎖了新的世界?
結(jié)論?#
通過(guò)使用 Javascript 腳本過(guò)濾器,我們可以非常靈活的進(jìn)行復(fù)雜邏輯的操作來(lái)滿足我們的業(yè)務(wù)需求。