Elasticsearch Painless Script詳解


1. Painless 簡介

自 ES 5.x 后引入,專門為 ES 設置,擴展了 Java 的語法
6.0 開始,ES 只支持 Painless。Grooby ,JavaScript 和 Python 都不在支持
Painless 支持所有的 Java 的數據類型及 Java API 子集
Painless Script 具備以下特性

  • 高性能 、 安全
  • 支持顯示類型或者動態定義類型

Painless 的用途

Painless 可以對文檔字段進行加工處理

  • 更新或者刪除字段,處理數據聚合操作
  • Script Field: 對返回的字段提前進行計算
  • Function Score:對文檔的算分進行處理

在 Ingest Pipeline 中執行腳本
在 Reindex API,Update By Query 時,對數據進行處理

  • 腳本編寫的語言,默認為painless。
  • 腳本本身可以指定為內聯腳本的source或存儲腳本的id。
  • 應傳遞給腳本的任何命名參數。

2. 參數

lang

  • 指定編寫腳本的語言,默認為painless。

source,id

  • 指定腳本的來源,inline腳本是指定source,,存儲的腳本是指定的id,並從群集狀態中檢索(請參閱存儲的腳本)。

params

  • 指定作為變量傳遞到腳本的任何命名參數。

3. 首選參數

Elasticsearch第一次看到一個新腳本,它會編譯它並將編譯后的版本存儲在緩存中,編譯可能是一個繁重的過程。

如果需要將變量傳遞給腳本,則應將它們作為命名參數傳遞給腳本本身而不是硬編碼值,例如,如果你希望能夠將字段值乘以不同的乘數,請不要將乘數硬編碼到腳本中:

"source": "doc['my_field'] * 2"

相反,將其作為命名參數傳遞:

  "source": "doc['my_field'] * multiplier",
  "params": {
    "multiplier": 2
  }

第一個版本每次乘數改變時都必須重新編譯,第二個版本只編譯一次。

如果你在很短的時間內編譯了太多獨特的腳本,Elasticsearch將使用circuit_breaking_exception錯誤拒絕新的動態腳本。默認情況下,每分鍾將編譯最多15個內聯腳本,你可以通過設置script.max_compilations_rate動態更改此設置。

4. 簡短腳本形式

可以使用簡短腳本形式來簡化,在簡短形式中,script由字符串而不是對象表示,該字符串包含腳本的源。

簡寫:

"script": "ctx._source.likes++"

正常形式的相同腳本:

  "script": {
    "source": "ctx._source.likes++"
  }

5. 通過 Painless 腳本訪問字段

上下文 語法
Ingestion ctx.field_name
Update ctx._source.field_name
Search & Aggregation doc["field_name"]

6. 示例

6.1 案例 1:Script Processsor

在這里插入圖片描述

# 增加一個 Script Prcessor
POST _ingest/pipeline/_simulate
{
  "pipeline": {
    "description": "to split blog tags",
    "processors": [
      {
        "split": {
          "field": "tags",
          "separator": ","
        }
      },
      {
        "script": {
          "source": """
          if(ctx.containsKey("content")){
            ctx.content_length = ctx.content.length();
          }else{
            ctx.content_length=0;
          }
        """
        }
      },
      {
        "set": {
          "field": "views",
          "value": 0
        }
      }
    ]
  },
  "docs": [
    {
      "_index": "index",
      "_id": "id",
      "_source": {
        "title": "Introducing big data......",
        "tags": "hadoop,elasticsearch,spark",
        "content": "You konw, for big data"
      }
    },
    {
      "_index": "index",
      "_id": "idxx",
      "_source": {
        "title": "Introducing cloud computering",
        "tags": "openstack,k8s",
        "content": "You konw, for cloud"
      }
    }
  ]
}

6.2 案例 2:文檔更新計數

在這里插入圖片描述

DELETE tech_blogs
PUT tech_blogs/_doc/1
{
  "title":"Introducing big data......",
  "tags":"hadoop,elasticsearch,spark",
  "content":"You konw, for big data",
  "views":0
}

POST tech_blogs/_update/1
{
  "script": {
    "source": "ctx._source.views += params.new_views",
    "params": {
      "new_views":100
    }
  }
}

# 查看views計數
POST tech_blogs/_search

6.3 案例 3:搜索時的 Script 字段

在這里插入圖片描述

GET tech_blogs/_search
{
  "script_fields": {
    "rnd_views": {
      "script": {
        "lang": "painless",
        "source": """
          java.util.Random rnd = new Random();
          doc['views'].value+rnd.nextInt(1000);
        """
      }
    }
  },
  "query": {
    "match_all": {}
  }
}

6.4 Script :Inline v.s Stored

在這里插入圖片描述

#保存腳本在 Cluster State
POST _scripts/update_views
{
  "script":{
    "lang": "painless",
    "source": "ctx._source.views += params.new_views"
  }
}

POST tech_blogs/_update/1
{
  "script": {
    "id": "update_views",
    "params": {
      "new_views":1000
    }
  }
}

6.5 示例4

首先,在集群狀態下創建名為calculate-score的腳本:

POST _scripts/calculate-score
{
  "script": {
    "lang": "painless",
    "source": "Math.log(_score * 2) + params.my_modifier"
  }
}

可以使用以下命令檢索相同的腳本:

GET _scripts/calculate-score

可以通過指定id參數來使用存儲的腳本,如下所示:

GET _search
{
  "query": {
    "script": {
      "script": {
        "id": "calculate-score",
        "params": {
          "my_modifier": 2
        }
      }
    }
  }
}

刪除:

DELETE _scripts/calculate-score

3. 緩存

編譯的開銷相較大
Elasticsearch 會將腳本編譯后緩存在 Cache 中

  • Inline scripts 和 Stored Scripts 都會被緩存
  • 默認緩存 100 個腳本
    在這里插入圖片描述

轉載自:https://blog.csdn.net/xixihahalelehehe/article/details/115203621
個人公眾號(大數據學習交流): hadoopwiki


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM