JavaScript?腳本實(shí)現(xiàn)復(fù)雜的查詢改寫示例
需求
網(wǎng)關(guān)里怎樣對跨集群搜索進(jìn)行支持的呢?我想實(shí)現(xiàn): 輸入的搜索請求是 lp:9200/index1/_search
這個索引在 3 個集群上,需要跨集群檢索,也就是網(wǎng)關(guān)能否改成 lp:9200/cluster01:index1,cluster02,index1,cluster03:index1/_search
呢?
索引有一百多個,名稱不一定是 app, 還可能多個索引一起的。
極限網(wǎng)關(guān)自帶的過濾器 content_regex_replace
雖然可以實(shí)現(xiàn)字符正則替換,但是這個需求是帶參數(shù)的變量替換,稍微復(fù)雜一點(diǎn),沒有辦法直接用這個正則替換實(shí)現(xiàn),有什么其他辦法實(shí)現(xiàn)么?
使用腳本過濾器
當(dāng)然有的,上面的這個需求,理論上我們只需要將其中的索引 index1
匹配之后,替換為 cluster01:index1,cluster02,index1,cluster03:index1
就行了。
答案就是使用自定義腳本來做,再復(fù)雜的業(yè)務(wù)邏輯都不是問題,都能通過自定義腳本來實(shí)現(xiàn),一行腳本不行,那就兩行。
使用極限網(wǎng)關(guān)提供的 JavaScript 過濾器可以很靈活的實(shí)現(xiàn)這個功能,具體繼續(xù)看。
定義腳本
首先創(chuàng)建一個腳本文件,放在網(wǎng)關(guān)數(shù)據(jù)目錄的 scripts
子目錄下面,如下:
? gateway ? tree data data └── gateway └── nodes └── c9bpg0ai4h931o4ngs3g ├── kvdb ├── queue ├── scripts │ └── index_path_rewrite.js └── stats
這個腳本的內(nèi)容如下:
function process(context) { var originalPath = context.Get("_ctx.request.path"); var matches = originalPath.match(/\/?(.*?)\/_search/) var indexNames = []; if(matches && matches.length > 1) { indexNames = matches[1].split(",") } var resultNames = [] var clusterNames = ["cluster01", "cluster02"] if(indexNames.length > 0) { for(var i=0; i<indexNames.length; i++){ if(indexNames[i].length > 0) { for(var j=0; j<clusterNames.length; j++){ resultNames.push(clusterNames[j]+":"+indexNames[i]) } } } } if (resultNames.length>0){ var newPath="/"+resultNames.join(",")+"/_search"; context.Put("_ctx.request.path",newPath); } }
和普通的 JavaScript 一樣,定義一個特定的函數(shù) process
來處理請求里面的上下文信息,_ctx.request.path
是網(wǎng)關(guān)內(nèi)置上下文的一個變量,用來獲取請求的路徑,通過 context.Get("_ctx.request.path")
在腳本里面進(jìn)行訪問。
中間我們使用了 JavaScript 的正則匹配和字符處理,做了一些字符拼接,得到新的路徑 newPath
變量,最后使用 context.Put("_ctx.request.path",newPath)
更新網(wǎng)關(guān)請求的路徑信息,從而實(shí)現(xiàn)查詢條件里面的參數(shù)替換。
定義網(wǎng)關(guān)
接下來,創(chuàng)建一個網(wǎng)關(guān)配置,并使用 javascript
過濾器調(diào)用該腳本,如下:
entry: - name: my_es_entry enabled: true router: my_router max_concurrency: 10000 network: binding: 0.0.0.0:8000 flow: - name: default_flow filter: - dump: context: - _ctx.request.path - javascript: file: index_path_rewrite.js - dump: context: - _ctx.request.path - elasticsearch: elasticsearch: dev router: - name: my_router default_flow: default_flow elasticsearch: - name: dev enabled: true schema: http hosts: - 192.168.3.188:9206
上面的例子中,使用了一個 javascript
過濾器,并且指定了加載的腳本文件為 index_path_rewrite.js
,并使用了兩個 dump
過濾器來輸出腳本運(yùn)行前后的路徑信息,最后再使用一個 elasticsearch
過濾器來轉(zhuǎn)發(fā)請求給 Elasticsearch 進(jìn)行查詢。
啟動網(wǎng)關(guān)
我們啟動網(wǎng)關(guān)測試一下,如下:
? gateway ? ./bin/gateway ___ _ _____ __ __ __ _ / _ \ /_\ /__ \/__\/ / /\ \ \/_\ /\_/\ / /_\///_\\ / /\/_\ \ \/ \/ //_\\\_ _/ / /_\\/ _ \/ / //__ \ /\ / _ \/ \ \____/\_/ \_/\/ \__/ \/ \/\_/ \_/\_/ [GATEWAY] A light-weight, powerful and high-performance elasticsearch gateway. [GATEWAY] 1.0.0_SNAPSHOT, 2022-04-18 07:11:09, 2023-12-31 10:10:10, 8062c4bc6e57a3fefcce71c0628d2d4141e46953 [04-19 11:41:29] [INF] [app.go:174] initializing gateway. [04-19 11:41:29] [INF] [app.go:175] using config: /Users/medcl/go/src/infini.sh/gateway/gateway.yml. [04-19 11:41:29] [INF] [instance.go:72] workspace: /Users/medcl/go/src/infini.sh/gateway/data/gateway/nodes/c9bpg0ai4h931o4ngs3g [04-19 11:41:29] [INF] [app.go:283] gateway is up and running now. [04-19 11:41:30] [INF] [api.go:262] api listen at: http://0.0.0.0:2900 [04-19 11:41:30] [INF] [entry.go:312] entry [my_es_entry] listen at: http://0.0.0.0:8000 [04-19 11:41:30] [INF] [module.go:116] all modules are started [04-19 11:41:30] [INF] [actions.go:349] elasticsearch [dev] is available
執(zhí)行測試
運(yùn)行下面的查詢來驗(yàn)證查詢結(jié)果,如下:
curl localhost:8000/abc,efg/_search
可以看到網(wǎng)關(guān)通過 dump
過濾器輸出的調(diào)試信息:
---- DUMPING CONTEXT ----
_ctx.request.path : /abc,efg/_search
---- DUMPING CONTEXT ----
_ctx.request.path : /cluster01:abc,cluster02:abc,cluster01:efg,cluster02:efg/_search
查詢條件按照我們的需求進(jìn)行了改寫,Nice!
重寫 DSL 查詢語句
好吧,我們剛剛只是修改了查詢的索引而已,那么查詢請求的 DSL 呢?行不行?
那自然是可以的嘛,瞧下面的例子:
function process(context) { var originalDSL = context.Get("_ctx.request.body"); if (originalDSL.length >0){ var jsonObj=JSON.parse(originalDSL); jsonObj.size=123; jsonObj.aggs= { "test1": { "terms": { "field": "abc", "size": 10 } } } context.Put("_ctx.request.body",JSON.stringify(jsonObj)); } }
先是獲取查詢請求,然后轉(zhuǎn)換成 JSON 對象,之后任意修改查詢對象就行了,保存回去,搞掂。
測試一下:
curl -XPOST localhost:8000/abc,efg/_search -d'{"query":{}}'
輸出:
---- DUMPING CONTEXT ----
_ctx.request.path : /abc,efg/_search
_ctx.request.body : {"query":{}}
[04-19 18:14:24] [INF] [reverseproxy.go:255] elasticsearch [dev] hosts: [] => [192.168.3.188:9206]
---- DUMPING CONTEXT ----
_ctx.request.path : /abc,efg/_search
_ctx.request.body : {"query":{},"size":123,"aggs":{"test1":{"terms":{"field":"abc","size":10}}}}
是不是感覺解鎖了新的世界?
結(jié)論
通過使用 Javascript 腳本過濾器,我們可以非常靈活的進(jìn)行復(fù)雜邏輯的操作來滿足我們的業(yè)務(wù)需求。
以上就是JavaScript 腳本實(shí)現(xiàn)復(fù)雜的查詢改寫示例的詳細(xì)內(nèi)容,更多關(guān)于JavaScript 復(fù)雜查詢改寫的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
'2'>'10'==true?解析JS如何進(jìn)行隱式類型轉(zhuǎn)換
這篇文章主要為大家介紹了'2'>'10'==true?解析JS如何進(jìn)行隱式類型轉(zhuǎn)換示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-09-09Server-sent?events實(shí)時獲取服務(wù)端數(shù)據(jù)技術(shù)詳解
這篇文章主要為大家介紹了Server-sent?events實(shí)時獲取服務(wù)端數(shù)據(jù)技術(shù)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-02-02基于JavaScript ES新特性let與const關(guān)鍵字
這篇文章主要介紹了基于JavaScript ES新特性let與const關(guān)鍵字,let是ECMAScript 2015新增的一個關(guān)鍵字,用于聲明變量,const關(guān)鍵字用于聲明一個常量,更多詳細(xì)內(nèi)容,請需要的小伙伴參考下面文章的介紹,希望對你有所幫助2021-12-12