ES 筆記四十五: Ingest Pipeline 與 Painless Script

CrazyZard發表於2020-01-15
  • Tags 欄位中,逗號分割的文字應該是陣列,而不是一個字串
    • 需求:後期需要對 Tags 進行 Aggregation 統計
  • Elasticsearch 5.0 後,引入的一種新的節點型別。預設配置下,每個節點都是 Ingest Node
    • 具有預處理資料的能力,可攔截 Index 或者 Bulck API 的請求
    • 對資料進行轉換,並重新返回給 Index 和 Bluck API
  • 無需 Logstash ,就可以進行資料的預處理,例如
    • 為某個欄位設定預設值;重新命名某個欄位的欄位名;對欄位值進行 Split 操作
    • 支援設定 Painless 指令碼,對資料進行更加複雜的加工
  • Pipeline - 管道會對通過的資料(文件),按照順序進行加工
  • Processor - Elasticsearch 對一些加工的行為進行了抽象包裝
    • Elasticsearch 有很多內建的 Processors。也支援通過外掛的方式,實現自己的 Processsor

ES筆記四十五: Ingest Pipeline 與 Painless Script

使用 Pipeline 切分字串

ES筆記四十五: Ingest Pipeline 與 Painless Script

# 測試split tags
POST _ingest/pipeline/_simulate
{
  "pipeline": {
    "description": "to split blog tags",
    "processors": [
      {
        "split": {
          "field": "tags",
          "separator": ","
        }
      }
    ]
  },
  "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"
      }
    }
  ]
}

為文件增加欄位

ES筆記四十五: Ingest Pipeline 與 Painless Script

#同時為文件,增加一個欄位。blog檢視量
POST _ingest/pipeline/_simulate
{
  "pipeline": {
    "description": "to split blog tags",
    "processors": [
      {
        "split": {
          "field": "tags",
          "separator": ","
        }
      },
      {
        "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"
      }
    }
  ]
}

Pipeline API

ES筆記四十五: Ingest Pipeline 與 Painless Script

新增 Pipeline 並測試

ES筆記四十五: Ingest Pipeline 與 Painless Script

# 為ES新增一個 Pipeline
PUT _ingest/pipeline/blog_pipeline
{
  "description": "a blog pipeline",
  "processors": [
    {
      "split": {
        "field": "tags",
        "separator": ","
      }
    },
    {
      "set": {
        "field": "views",
        "value": 0
      }
    }
  ]
}
#測試pipeline
POST _ingest/pipeline/blog_pipeline/_simulate
{
  "docs": [
    {
      "_source": {
        "title": "Introducing cloud computering",
        "tags": "openstack,k8s",
        "content": "You konw, for cloud"
      }
    }
  ]
}

Index & Update By Query

ES筆記四十五: Ingest Pipeline 與 Painless Script

#不使用pipeline更新資料
PUT tech_blogs/_doc/1
{
  "title":"Introducing big data......",
  "tags":"hadoop,elasticsearch,spark",
  "content":"You konw, for big data"
}

#使用pipeline更新資料
PUT tech_blogs/_doc/2?pipeline=blog_pipeline
{
  "title": "Introducing cloud computering",
  "tags": "openstack,k8s",
  "content": "You konw, for cloud"
}

#檢視兩條資料,一條被處理,一條未被處理
POST tech_blogs/_search
{}

#update_by_query 會導致錯誤
POST tech_blogs/_update_by_query?pipeline=blog_pipeline
{
}

#增加update_by_query的條件
POST tech_blogs/_update_by_query?pipeline=blog_pipeline
{
  "query": {
    "bool": {
      "must_not": {
        "exists": {
          "field": "views"
        }
      }
    }
  }
}

一些內建的 Processors

  • https://www.elastic.co/guide/en/elasticsea...
    • Split Processor (例如:將給定欄位分成一個陣列)
    • Remove / Rename Processor (移除一個重新命名欄位)
    • Append(為商品增加一個新的標籤)
    • Convert (將商品價格,從字串轉換成 float 型別)
    • Date / JSON (日期格式轉換,字串轉 JSON 物件)
    • Date Index Name Processor (將通過該處理器的文件,分配到指定時間格式的索引中)
    • Fail Processor (一旦出現異常,該 Pipeline 指定的錯誤資訊能返回給使用者)
    • Foreach Process (陣列欄位,陣列的每個元素都會使用到一個相同的處理器)
    • Grok Processor (日誌的日誌格式切割)
    • Gsub / Join / Split (字串替換、陣列轉字串、字串轉陣列)
    • Lowercase / Upcase(大小寫轉換)

Ingest Node v.s Logstash

Logstash Ingest Node
資料輸入與輸出 支援從不同的資料來源讀取,並寫入不同的資料來源 支援從ES REST API 獲取資料,並且寫入ES
資料來源緩衝 實現了簡單的資料佇列,支援重寫 不支援緩衝
資料處理 支援大量的的外掛,也支援定製開發 內建的外掛,可以開發 Plugin 進行擴充套件(Plugin 更新需要重啟)
配置和使用 增加了一定的架構複雜度 無需額外部署

https://www.elastic.co/cn/blog/should-i-us...

  • 自 ES 5.x 後引入,專門為 ES 設定,擴充套件了 Java 的語法
  • 6.0 開始,ES 只支援 Painless。Grooby ,JavaScript 和 Python 都不在支援
  • Painless 支援所有的 Java 的資料型別及 Java API 子集
  • Painless Script 具備以下特性
    • 高效能 、 安全
    • 支援顯示型別或者動態定義型別

Painless 的用途

  • 可以對文件欄位進行加工處理
    • 更新或者刪除欄位,處理資料聚合操作
    • Script Field: 對返回的欄位提前進行計算
    • Function Score:對文件的算分進行處理
  • 在Ingest Pipeline 中執行指令碼
  • 在Reindex API,Update By Query 時,對資料進行處理

通過 Painless 指令碼訪問欄位

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

案例1:Script Processsor

ES筆記四十五: Ingest Pipeline 與 Painless Script

# 增加一個 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"
      }
    }
  ]
}

案例2:文件更新計數

ES筆記四十五: Ingest Pipeline 與 Painless Script

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

案例3:搜尋時的Script 欄位

ES筆記四十五: Ingest Pipeline 與 Painless 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": {}
  }
}

Script :Inline v.s Stored

ES筆記四十五: Ingest Pipeline 與 Painless Script

#儲存指令碼在 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
    }
  }
}

指令碼快取

  • 編譯的開銷相較大
  • Elasticsearch 會將甲苯編譯後快取在 Cache 中
    • Inline scripts 和 Stored Scripts 都會被快取
    • 預設快取 100個指令碼
      ES筆記四十五: Ingest Pipeline 與 Painless Script
  • 概念講解:Ingest Node,Pipeline 與 Processor
  • Ingest Node 與 Logstash 的⽐較
  • Pipeline 的 相關操作 / 內建 Processor 講解與演示
  • Painless 指令碼與
    • Ingestion (Pipeline)
    • Update
    • Search & Aggregation
本作品採用《CC 協議》,轉載必須註明作者和本文連結

快樂就是解決一個又一個的問題!

相關文章