JavaScript?腳本實現復雜的查詢改寫示例
需求
網關里怎樣對跨集群搜索進行支持的呢?我想實現: 輸入的搜索請求是 lp:9200/index1/_search這個索引在 3 個集群上,需要跨集群檢索,也就是網關能否改成 lp:9200/cluster01:index1,cluster02,index1,cluster03:index1/_search 呢?
索引有一百多個,名稱不一定是 app, 還可能多個索引一起的。
極限網關自帶的過濾器 content_regex_replace 雖然可以實現字符正則替換,但是這個需求是帶參數的變量替換,稍微復雜一點,沒有辦法直接用這個正則替換實現,有什么其他辦法實現么?
使用腳本過濾器
當然有的,上面的這個需求,理論上我們只需要將其中的索引 index1 匹配之后,替換為 cluster01:index1,cluster02,index1,cluster03:index1 就行了。
答案就是使用自定義腳本來做,再復雜的業(yè)務邏輯都不是問題,都能通過自定義腳本來實現,一行腳本不行,那就兩行。
使用極限網關提供的 JavaScript 過濾器可以很靈活的實現這個功能,具體繼續(xù)看。
定義腳本
首先創(chuàng)建一個腳本文件,放在網關數據目錄的 scripts 子目錄下面,如下:
? gateway ? tree data
data
└── gateway
└── nodes
└── c9bpg0ai4h931o4ngs3g
├── kvdb
├── queue
├── scripts
│ └── index_path_rewrite.js
└── stats這個腳本的內容如下:
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 一樣,定義一個特定的函數 process 來處理請求里面的上下文信息,_ctx.request.path 是網關內置上下文的一個變量,用來獲取請求的路徑,通過 context.Get("_ctx.request.path") 在腳本里面進行訪問。
中間我們使用了 JavaScript 的正則匹配和字符處理,做了一些字符拼接,得到新的路徑 newPath 變量,最后使用 context.Put("_ctx.request.path",newPath) 更新網關請求的路徑信息,從而實現查詢條件里面的參數替換。
定義網關
接下來,創(chuàng)建一個網關配置,并使用 javascript 過濾器調用該腳本,如下:
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 過濾器來輸出腳本運行前后的路徑信息,最后再使用一個 elasticsearch 過濾器來轉發(fā)請求給 Elasticsearch 進行查詢。
啟動網關
我們啟動網關測試一下,如下:
? 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í)行測試
運行下面的查詢來驗證查詢結果,如下:
curl localhost:8000/abc,efg/_search
可以看到網關通過 dump 過濾器輸出的調試信息:
---- DUMPING CONTEXT ----
_ctx.request.path : /abc,efg/_search
---- DUMPING CONTEXT ----
_ctx.request.path : /cluster01:abc,cluster02:abc,cluster01:efg,cluster02:efg/_search
查詢條件按照我們的需求進行了改寫,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));
}
}先是獲取查詢請求,然后轉換成 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}}}}
是不是感覺解鎖了新的世界?
結論
通過使用 Javascript 腳本過濾器,我們可以非常靈活的進行復雜邏輯的操作來滿足我們的業(yè)務需求。
以上就是JavaScript 腳本實現復雜的查詢改寫示例的詳細內容,更多關于JavaScript 復雜查詢改寫的資料請關注腳本之家其它相關文章!
相關文章
JavaScript?Canvas實現噪點濾鏡回憶童年電視雪花屏
這篇文章主要為大家介紹了JavaScript?Canvas實現噪點濾鏡回憶童年電視雪花屏,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-09-09
Web?Animations?API實現一個精確計時的時鐘示例
這篇文章主要為大家介紹了Web?Animations?API實現一個精確計時的時鐘示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-07-07
jQuery幻燈片插件owlcarousel參數說明中文文檔
jQuery幻燈片插件owlcarousel是一個小巧強大兼容性強的幻燈片插件,兼容IE6以上所有瀏覽器,本文主要介紹了字的使用方法與中文參數與API說明2018-02-02

