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進行修改。放置在這個目錄中的腳本會自動選中而且能夠被使用。一旦腳本被放在這個目錄中,能夠經過腳本名進行引用。
在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
}
}
}
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的最新版本的各項功能進行分析,近請期待。