Painless script在ElasticSearch 中的使用的一些問題

Painless script在ElasticSearch 中的使用的一些問題

最近在準(zhǔn)備ElasticSearch認證工程師的考試,其中Script是比較重要西潘,也是比較難的部分卷玉。在這里做一下總結(jié)的,主要是自己在做真題時不確定的一些東西喷市。

使用場景

Script使用場景比較多相种,在做真題的過程中,我遇到過下面一些場景:

  • Ingress Pipeline中使用品姓。
  • reindex索引時使用寝并。
  • query時使用。
    • 使用script產(chǎn)生一個新的field腹备,加入到搜索出的文檔中衬潦。
    • 作為filter的內(nèi)嵌函數(shù)。對結(jié)果進行過濾植酥。
    • 在function_score中使用镀岛,取代算分。
  • search template中使用友驮。
  • update/update_by_query中使用漂羊。(7.x版本似乎這個功能有bug,做父子關(guān)聯(lián)更新時卸留,提示父子文檔需要在同一個分片上走越,但是一共只有一個分片)
  • 排序中使用。產(chǎn)生一個metric作為排序指標(biāo)耻瑟。
  • 在filter中使用旨指。

官網(wǎng)上還有一些其他的使用場景赏酥,比如在聚合中使用script,似乎一直沒有在真題中見過谆构。

Painless腳本語言

本文的主角painless腳本裸扶,是Java語言的一個子集,很多地方的用法和Java是類似的低淡,但是也有一些不一樣的地方姓言。之前使用的時候,我一直當(dāng)做Java在寫蔗蹋,其實踩了不少坑。painless的主要API其實是在[painless API reference] > [Shard API]里面囱淋,官方文檔的位置在https://www.elastic.co/guide/en/elasticsearch/painless/7.2/painless-api-reference-shared.html猪杭。這個位置我也是寫本文的時候才發(fā)現(xiàn)的⊥滓拢看了這部分文檔皂吮,揭開了之前的一些疑惑。

比如說税手,把一個字符串按照空格分割成一個字符串?dāng)?shù)組蜂筹,我之前使用java的split API來進行分解,ES報錯找不到相關(guān)接口芦倒。后來在文檔中發(fā)現(xiàn)painless的相關(guān)API是String[] splitOnToken(String)艺挪。當(dāng)然,正是因為這個兵扬,我有機會接觸到了ingest pipeline中的grok以及splite processor麻裳。

其他比較多的一些用法有:

  • 訪問某個field

在painless里面,文檔的field數(shù)據(jù)要么直接存儲在ctx中(ingest器钟,reindex)津坑,要么存儲在ctx的成員ctx._source中,這倆個對象傲霸,都是map類型的疆瑰,在painless中可以有兩種方法進行訪問。以ctx._source為例昙啄,假設(shè)有一個field叫做apple穆役,我們可以使用ctx._source['apple']或者ctx._source.apple進行訪問。

  • 判斷field是否存在

比如說跟衅,判斷apple字段是否存在孵睬,我可以用if (ctx._source.apple == null)進行判斷。又因為ctx._source是一個hashmap伶跷,我們也可以用map的相關(guān)API進行判斷:if (ctx._source.containKey('apple'))掰读。

  • 設(shè)置新field

上文曾經(jīng)描述秘狞,可以使用ctx['key_name']ctx.key_name這種方法來對hashmap的字段進行訪問。這種方法統(tǒng)一可以用來設(shè)置新的值蹈集。

ctx['key_name'] = value;
ctx.key_name = value; 
  • String轉(zhuǎn)換成int

可以使用Integer的函數(shù)parseInt來進行轉(zhuǎn)換烁试。比如說:

String num = '123';
int num_int = Integer.parseInt(num);

其實這個用法和Java是一樣的,轉(zhuǎn)換成其他數(shù)字類型也是一樣的拢肆。

  • 單值或者數(shù)組

這個場景其實我并沒有在實際的題目中看到减响,但是這個場景我覺得是非常可能出現(xiàn)的郭怪,因為ES有個特性支示,當(dāng)我們?yōu)槟硞€字段做映射時,我們可以指定其類型鄙才,比如說颂鸿,指定為text。在實際寫入文檔時攒庵,我們可以寫入一個值嘴纺,或者是多個值組成的數(shù)組。那么問題就來了浓冒,我怎樣在painless腳本里處理這樣的情況呢栽渴?我并沒有機會知道,我獲得的一個值是一個String還是一個ArrayList稳懒。那這種情況怎么處理呢闲擦?查看painless的關(guān)鍵字https://www.elastic.co/guide/en/elasticsearch/painless/7.2/painless-keywords.html,可以發(fā)現(xiàn)僚祷,和Java一樣佛致,painless有關(guān)鍵字instanceof。我們可以使用instanceof來對類型進行判斷辙谜。

進行一個小實驗俺榆,假設(shè)有一個index,其包含一個字段tags装哆,tags可以是一個罐脊,也可以是多個。

PUT test1
{
  "settings": {
    "number_of_shards": 1,
    "number_of_replicas": 0
  },
  "mappings": {
    "properties": {
      "tags": {
        "type": "keyword"
      }
    }
  }
}

POST test1/_bulk
{"index": {"_id": 1}}
{"tags": "cat"}
{"index": {"_id": 2}}
{"tags": ["cat", "dog"]}
{"index": {"_id": 3}}
{"tags": ["cat", "dog", "tiger"]}

我們要將索引test1重新導(dǎo)入到索引test2中蜕琴,并且增加一個字段將所有的tag拼接起來萍桌。tags字段現(xiàn)在可能是String,也可能是一個ArrayList凌简。因此我們再寫painless腳本時要注意識別tags的類型上炎。

PUT _ingest/pipeline/join_tags
{
  "description": "join_tags",
  "processors": [
    {
      "script": {
        "lang": "painless",
        "source": """
        ctx.tags_str = "";
        if (ctx.tags instanceof ArrayList)
        {
          for (String tag: ctx.tags)
          {
            if (ctx.tags_str.length() > 0)
            {
              ctx.tags_str += " " + tag;
            }
            else
            {
              ctx.tags_str = tag;
            }
          }
        }
        else
        {
          ctx.tags_str = ctx.tags
        }
        """
      }
    }
  ]
}

好了,現(xiàn)在可以用_reindex來將test1導(dǎo)入到test2中了。

POST _reindex
{
  "source": {
    "index": "test1"
  },
  "dest": {
    "index": "test2",
    "pipeline": "join_tags"
  }
}

順便提一句藕施,_reindex里面也可以直接寫script寇损,但是就像上面提到的,處理父子關(guān)系時會出問題裳食。

小結(jié)

上面就是我這幾天做題遇到的一些場景矛市,當(dāng)時做的時候,其實還遇到不少其他情況诲祸,不過現(xiàn)在記得不是很清楚了浊吏。等我后面想起來再做補充吧。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末救氯,一起剝皮案震驚了整個濱河市找田,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌着憨,老刑警劉巖午阵,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異享扔,居然都是意外死亡,警方通過查閱死者的電腦和手機植袍,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進店門惧眠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人于个,你說我怎么就攤上這事氛魁。” “怎么了厅篓?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵秀存,是天一觀的道長。 經(jīng)常有香客問我羽氮,道長或链,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任档押,我火速辦了婚禮澳盐,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘令宿。我一直安慰自己叼耙,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布粒没。 她就那樣靜靜地躺著筛婉,像睡著了一般。 火紅的嫁衣襯著肌膚如雪癞松。 梳的紋絲不亂的頭發(fā)上爽撒,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天入蛆,我揣著相機與錄音,去河邊找鬼匆浙。 笑死安寺,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的首尼。 我是一名探鬼主播挑庶,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼软能!你這毒婦竟也來了迎捺?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤查排,失蹤者是張志新(化名)和其女友劉穎凳枝,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體跋核,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡岖瑰,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了砂代。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蹋订。...
    茶點故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖刻伊,靈堂內(nèi)的尸體忽然破棺而出露戒,到底是詐尸還是另有隱情,我是刑警寧澤捶箱,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布智什,位于F島的核電站,受9級特大地震影響丁屎,放射性物質(zhì)發(fā)生泄漏荠锭。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一悦屏、第九天 我趴在偏房一處隱蔽的房頂上張望节沦。 院中可真熱鬧,春花似錦础爬、人聲如沸甫贯。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽叫搁。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間渴逻,已是汗流浹背疾党。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留惨奕,地道東北人雪位。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像梨撞,于是被迫代替她去往敵國和親雹洗。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,577評論 2 353

推薦閱讀更多精彩內(nèi)容