Elasticsearch 2.3.0 腳本篇

Elasticsearch的腳本模塊可使用腳本對Elasticsearch的字段進行再次處理。例如,能夠用來從新評估查詢的自定義得分,能夠對索引中的某個字段再次加工處理。javascript

腳本默認是關閉的,若是這個時候執行腳本會報如下錯誤:java

{python

"error": {linux

"root_cause": [express

{數組

"type": "remote_transport_exception",緩存

"reason": "[Left-Winger][127.0.0.1:9300][indices:data/write/update[s]]"安全

}],服務器

"type": "illegal_argument_exception",app

"reason": "failed to execute script",

"caused_by": {

"type": "script_exception",

"reason": "scripts of type [indexed], operation [update] and lang [groovy] are disabled"

}

},

"status": 400

}

能夠經過配置來啓用腳本引擎,配置的位置在elasticsearch.yml文件中添加以下內容:

script.inline: true

script.indexed: true

對這些設置,有三種配置值:

描述

false

徹底禁用腳本

true

啓用腳本

sandbox

腳本僅能夠用沙盒語言執行

表格 8.7 細粒度動態腳本設置

默認配置值爲:

script.inline: sandbox

script.indexed: sandbox

script.file: true

也能夠在已下操做中執行腳本:

描述

aggs

聚合

search

搜索接口、過濾接口或建議接口(例如filters、script_fields)。

update

升級接口

plugin

通用plugin類別下,腳本使用的任何插件

插件也能夠進行自定義操做,利用這種格式:${pluginName}_${operation}。例如在任何腳本引擎上禁用更新和映射:

script.update: false

script.mapping: false

也支持明確的腳本語言設置,須要script.engine.<engine>前綴,優先權高於其餘通用設置:

script.engine.groovy.file.aggs: true

script.engine.groovy.file.mapping: true

script.engine.groovy.file.search: true

script.engine.groovy.file.update: true

script.engine.groovy.file.plugin: true

script.engine.groovy.indexed.aggs: true

script.engine.groovy.indexed.mapping: false

script.engine.groovy.indexed.search: true

script.engine.groovy.indexed.update: false

script.engine.groovy.indexed.plugin: false

script.engine.groovy.inline.aggs: true

script.engine.groovy.inline.mapping: false

script.engine.groovy.inline.search: false

script.engine.groovy.inline.update: false

script.engine.groovy.inline.plugin: false

 

系統的腳本模塊默認使用groovy做爲的腳本語言。能夠經過設置script.default_lang能夠進行修改。

能夠用語言插件來支持不一樣的語言腳本。因此在使用腳本接口的參數中提供了lang參數定義腳本語言。

語言

沙盒

必要插件

groovy

內置

expression

內置

mustache

內置

javascript

elasticsearch-lang-javascript

python

elasticsearch-lang-python

爲了增長安全性,Elasticsearch不容許在請求中指定非沙盒語言。默認的腳本目錄位置能夠在elasticsearch.yml中設置path.scripts進行修改。放置在這個目錄中的腳本會自動選中而且能夠被使用。一旦腳本被放在這個目錄中,能夠經過腳本名進行引用。

1.1.1 腳本使用

在Elasticsearch中使用腳本有三種方式:

一、直接在請求體中使用腳本。

二、把腳本存儲在索引中,經過引用腳本id來使用。

三、把腳本存儲在本地磁盤中,默認的位置爲:elasticsearch\config\scripts,經過引用腳本名稱進行使用。

下面經過舉例來講明使用腳本的三種方法。

首先建一個索引,添加一條數據。

PUT localhost:9200/secisland/secilog/1

{

"eventCount":1,

"eventName" :"linux login event"

}

下面咱們用腳本對eventCount作加法操做。

n 用第一種方法直接在請求中執行腳本:

http://127.0.0.1:9200/secisland/secilog/1/_update

{

    "script" : "ctx._source.eventCount+=count",

    "params" : {

        "count" : 4

    }

}

n 下面咱們用第二種方法操做,在用第二種方法前,先要把腳本存儲在Elasticsearch中:

POST 127.0.0.1:9200/_scripts/groovy/indexedCalculateCount 

{

     "script": "ctx._source.eventCount+=count"

}

而後經過腳本Id進行文檔操做:

POST http://127.0.0.1:9200/secisland/secilog/1/_update

{

  "script": {

    "id": "indexedCalculateCount",

    "lang": "groovy",

    "params": {

      "count": 8

    }

  }

}

n 下面咱們用第三種方法操做,在第三種方法操做前,先要把腳本存儲在文件中,文件名爲indexedCalculateCount.groovy,文件中的內容爲:ctx._source.eventCount+=count。

注意:Elasticsearch對文件讀取有個時間,剛建好後,不能生效,作驗證的時候能夠重啓進行生效。

POST http://127.0.0.1:9200/secisland/secilog/1/_update/

{

  "script": {

    "file": "indexedCalculateCount",

    "lang": "groovy",

    "params": {

      "count": 8

    }

  }

}

1.1.2 腳本配置

A. 索引腳本

Elasticsearch能夠在名爲_scripts的內部索引中存儲腳本,而且經過id進行引用。腳本請求的格式:/_scripts/{lang}/{id}

lang表示腳本語言,id表示腳本編號。

1. 保存腳本

POST localhost:9200/_scripts/groovy/indexedCalculateScore

{

     "script": "log(_score * 2) + my_modifier"

}

2. 使用腳本

POST localhost:9200/_search

{

  "query": {

    "function_score": {

      "query": {

        "match": {

          "body": "foo"

        }

      },

      "functions": [

        {

          "script_score": {

            "script": {

              "id": "indexedCalculateScore",

              "lang" : "groovy",

              "params": {

                "my_modifier": 8

              }

            }

          }

        }

      ]

    }

  }

}

3. 查看腳本

GET localhost:9200/_scripts/groovy/indexedCalculateScore

4. 刪除腳本

DELETE localhost:9200/_scripts/groovy/indexedCalculateScore

B. 啓用動態腳本

在應用或代理後面執行Elasticsearch,能夠從外界保護Elasticsearch。若是容許用戶運行內聯腳本或索引腳本,會繼承運行Elasticsearch的用戶權限。所以動態腳本默認僅支持沙盒語言。

首先,應該使用root用戶權限運行Elasticsearch,能夠容許腳本在服務器上訪問或作任何事情。其次,不該該讓用戶直接訪問Elasticsearch,而是要有一箇中間代理應用。若是確實想要用戶直接訪問Elasticsearch,須要決定是否足夠信任用戶來運行腳本。

C. 腳本自動重載

週期性掃描config/scripts目錄的修改。新的和修改的腳本會被重載刪除的腳本會從預加載腳本緩存中移除。重載頻率可使用resource.reload.interval設置指定,默認值爲60s。設置script.auto_reload_enabled爲false能夠徹底禁用腳本重載。

本文由賽克 藍德(secisland)原創,轉載請標明做者和出處。

D. 本地(Java)腳本

有時,groovy和expressions是不夠的。在這種狀況下,能夠執行本地腳本。

執行本地腳本的最好方式是編寫而且安裝一個插件。

爲了註冊實際腳本,須要引用NativeScriptFactory來構成腳本。實際腳本須要繼承AbstractExecutableScript或AbstractSearchScript。第二種多是最有用的而且有多個能夠繼承的子類,好比AbstractLongSearchScript、AbstractDoubleSearchScript和AnstractFloatSearchScript。最後,插件須要經過onModule(ScriptModule)方法註冊本地腳本。

public class MyNativeScriptPlugin extends Plugin {

    @Override

    public String name() {

        return "my-native-script";

    }

    @Override

    public String description() {

        return "my native script that does something great";

    }

    public void onModule(ScriptModule scriptModule) {

        scriptModule.registerScript("my_script", MyNativeScriptFactory.class);

    }

 

    public static class MyNativeScriptFactory implements NativeScriptFactory {

        @Override

        public ExecutableScript newScript(@Nullable Map<String, Object> params) {

            return new MyNativeScript();

        }

        @Override

        public boolean needsScores() {

            return false;

        }

    }

 

    public static class MyNativeScript extends AbstractFloatSearchScript {

        @Override

        public float runAsFloat() {

            float a = (float) source().get("a");

            float b = (float) source().get("b");

            return a * b;

        }

    }

}

能夠執行腳本經過指定lang爲native,指定inline爲腳本名。

POST localhost:9200/_search

{

  "query": {

    "function_score": {

      "query": {

        "match": {

          "body": "foo"

        }

      },

      "functions": [

        {

          "script_score": {

            "script": {

                "inline": "my_script",

                "lang" : "native"

            }

          }

        }

      ]

    }

  }

}

E. Lucene表達式腳本

警告:Lucene表達式模塊正經歷重大的發展,展示的功能可能會被修改。

Lucene的表達式模塊提供了一個機制來將Javascript表達式編譯成字節碼。表達式腳本能夠用於script_score、script_fields、排序腳本和數字型聚合腳本。

表達式腳本變量能夠接受:

l 單值文檔字段,例如doc[‘myfield’].value,也能夠寫做doc[‘myfield’]。

l 傳給腳本的參數,例如mymodifier。

l 當前文檔的得分,_score(只有用在script_score的時候)。

表達式腳本日期類型可使用這些方法:

l getYear()

l getMonth()

l getDayOfMonth()

l getHourOfDay()

l getMinutes()

l getSeconds()

好比,獲取日期字段間年份的不一樣:

doc[‘date1’].getYear() – doc[‘date0’].getYear()

相對於其餘腳本語言,有一些限制:

l 只接受數字型字段

l 保存的字段不可用

l 若是隻有一部分文檔包含字段值,缺失字段值的文檔默認值爲0。

F. 得分

聚合中全部可使用的腳本,當前文檔的得分能夠用_score得到。

G. 文檔字段

大多數腳本圍繞指定文檔字段數據的使用。doc[‘field_name’]能夠用來訪問文檔內指定字段數據。注意,只能是簡單值字段(不能返回Json對象)而且只有不分詞字段或單索引詞字段是有意義的。

能夠從字段中獲取下列數據:

表達式

描述

doc[‘field_name’].value

字段的本地值。

doc[‘field_name’].values

字段的本地數組值。若是字段沒有值,返回一個空數組。

doc[‘field_name’].empty

布爾值,表示文檔中的字段是否有值。

doc[‘field_name’].multiValued

布爾值,表示文集中有多個值的字段。

doc[‘field_name’].lat

地理點類型的緯度。

doc[‘field_name’].lon

地理點類型的經度。

doc[‘field_name’].lats

地理點類型的緯度(複數)。

doc[‘field_name’].lons

地理點類型的經度(複數)。

doc[‘field_name’].distance(lat,lon)

地理點字段和提供的經緯度之間的平面距離(米)。

doc[‘field_name’].distanceWithDefault(lat,lon,default)

地理點字段從提供的經緯度和默認值的平面距離(米)。

doc[‘field_name’].distanceInMiles(lat,lon)

地理點字段和提供的經緯度之間的平面距離(英里)。

doc[‘field_name’].distanceInMilesWithDefault(lat,lon,default)

地理點字段從提供的經緯度和默認值的平面距離(英里)。

doc[‘field_name’].distanceInKm(lat,lon)

地理點字段和提供的經緯度之間的平面距離(公里)。

doc[‘field_name’].distanceInkmWithDefault(lat,lon,default)

地理點字段從提供的經緯度和默認值的平面距離(公里)。

doc[‘field_name’].arcDistance(lat,lon)

地理點字段和提供的經緯度之間的天穹距離(米)。

doc[‘field_name’].arcDistanceWithDefault(lat,lon,default)

地理點字段從提供的經緯度和默認值的天穹距離(米)。

doc[‘field_name’].arcDistanceInMiles(lat,lon)

地理點字段和提供的經緯度之間的天穹距離(英里)。

doc[‘field_name’].arcDistanceInMilesWithDefault(lat,lon,default)

地理點字段從提供的經緯度和默認值的天穹距離(英里)。

doc[‘field_name’].arcDistanceInKm(lat,lon)

地理點字段和提供的經緯度之間的天穹距離(公里)。

doc[‘field_name’].arcDistanceInKmWithDefault(lat,lon,default)

地理點字段從提供的經緯度和默認值的天穹距離(公里)。

doc[‘field_name’].factorDistance(lat,lon)

地理點字段從提供的經緯度之間的距離因子。

doc[‘field_name’].factorDistance(lat,lon,default)

地理點字段從提供的經緯度和默認值的距離因子。

doc[‘field_name’].geohashDistance(geohash)

地理點字段從提供的地理散列的天穹距離(米)。

doc[‘field_name’].geohashDistanceInKm(geohash)

地理點字段從提供的地理散列的天穹距離(公里)。

doc[‘field_name’].geohashDistanceInMiles(geohash)

地理點字段從提供的地理散列的天穹距離(英里)。

表格 8.9 腳本提取數據

H. 保存的字段

執行腳本的時候,保存的字段也能夠訪問。經過使用_fields[‘my_field_name’].value或_fields[‘my_field_name’].values。

I. 在腳本中訪問文檔的得分

當使用腳本計算文檔得分(例如,經過function_score查詢),能夠在groovy腳本中使用_score變量訪問得分。

J. 源字段

當執行腳本的時候,能夠訪問源字段。每一個文檔都會加載源字段、分析而且提供給腳本進行評估。使用方式,形如_source.obj1.obj2.field3。

K. Groovy內置方法

方法

描述

sin(a)

返回角度的三角正弦

cos(a)

返回角度的三角餘弦

tan(a)

返回角度的三角正切

asin(a)

返回反正弦值

acos(a)

返回反餘弦值

atan(a)

返回反正切值

toRadians(angdeg)

轉換角度度量近似爲弧度

toDegrees(angrad)

轉換弧度度量近似爲角度

exp(a)

返回歐拉數e的指數值

log(a)

返回值的天然對數(基於e)

log10(a)

返回值基於10的對數

sqrt(a)

返回值的平方根

cbrt(a)

返回雙精度值的立方根

IEEEremainder(f1,f2)

進行餘數運算

ceil(a)

向下取整

floor(a)

向上取整

rint(a)

取整

atan2(y,x)

轉換直角座標(x,y)到極座標(r,θ),返回θ值

pow(a,b)

返回ab

round(a)

取整

random()

返回隨機雙精度數

abs(a)

返回值的絕對值

max(a,b)

返回大值

min(a,b)

返回小值

ulp(d)

返回參數的ulp的大小

signum(d)

返回自變量的符號函數

sinh(x)

返回值的雙曲正弦值

cosh(x)

返回值的雙曲餘弦值

tanh(x)

返回值的雙曲切線

hypot(x,y)

返回sqrt(x2+y2)

賽克藍德(secisland)後續會逐步對Elasticsearch的最新版本的各項功能進行分析,近請期待。

相關文章
相關標籤/搜索