JavaScript?腳本實(shí)現(xiàn)復(fù)雜的查詢改寫(xiě)示例
需求
網(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),沒(méi)有辦法直接用這個(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 子目錄下面,如下:
? gateway ? tree data
data
└── gateway
└── nodes
└── c9bpg0ai4h931o4ngs3g
├── kvdb
├── queue
├── scripts
│ └── index_path_rewrite.js
└── stats這個(gè)腳本的內(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 一樣,定義一個(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ù)替換。
定義網(wǎng)關(guān)
接下來(lái),創(chuàng)建一個(gè)網(wǎng)關(guān)配置,并使用 javascript 過(guò)濾器調(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上面的例子中,使用了一個(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è)試一下,如下:
? 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í)行測(cè)試
運(yùn)行下面的查詢來(lái)驗(yàn)證查詢結(jié)果,如下:
curl localhost:8000/abc,efg/_search
可以看到網(wǎng)關(guān)通過(guò) dump 過(guò)濾器輸出的調(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)行了改寫(xiě),Nice!
重寫(xiě) DSL 查詢語(yǔ)句
好吧,我們剛剛只是修改了查詢的索引而已,那么查詢請(qǐng)求的 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));
}
}先是獲取查詢請(qǐng)求,然后轉(zhuǎn)換成 JSON 對(duì)象,之后任意修改查詢對(duì)象就行了,保存回去,搞掂。
測(cè)試一下:
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}}}}
是不是感覺(jué)解鎖了新的世界?
結(jié)論
通過(guò)使用 Javascript 腳本過(guò)濾器,我們可以非常靈活的進(jìn)行復(fù)雜邏輯的操作來(lái)滿足我們的業(yè)務(wù)需求。
以上就是JavaScript 腳本實(shí)現(xiàn)復(fù)雜的查詢改寫(xiě)示例的詳細(xì)內(nèi)容,更多關(guān)于JavaScript 復(fù)雜查詢改寫(xiě)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
JavaScript?Canvas實(shí)現(xiàn)噪點(diǎn)濾鏡回憶童年電視雪花屏
這篇文章主要為大家介紹了JavaScript?Canvas實(shí)現(xiàn)噪點(diǎn)濾鏡回憶童年電視雪花屏,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09
JavaScript實(shí)現(xiàn)隊(duì)列結(jié)構(gòu)過(guò)程
這篇文章主要介紹了JavaScript實(shí)現(xiàn)隊(duì)列結(jié)構(gòu)的過(guò)程,隊(duì)列即Queue,它是受限的線性表,先進(jìn)先出,受限之處在于它只允許在表的前端進(jìn)行刪除操作,下面我們一起進(jìn)入文章學(xué)習(xí)更加詳細(xì)內(nèi)容,需要的朋友也可以參考一下2021-12-12
Web?Animations?API實(shí)現(xiàn)一個(gè)精確計(jì)時(shí)的時(shí)鐘示例
這篇文章主要為大家介紹了Web?Animations?API實(shí)現(xiàn)一個(gè)精確計(jì)時(shí)的時(shí)鐘示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-07-07
jQuery幻燈片插件owlcarousel參數(shù)說(shuō)明中文文檔
jQuery幻燈片插件owlcarousel是一個(gè)小巧強(qiáng)大兼容性強(qiáng)的幻燈片插件,兼容IE6以上所有瀏覽器,本文主要介紹了字的使用方法與中文參數(shù)與API說(shuō)明2018-02-02

