ElasticSearch笔记-管道(pipeline)
摄取节点(ingest)
ES集群中存在一个摄取节点,在数据保存到文档索引之前,我们可能需要对文档进行预处理,而摄取节点会拦截这些请求,根据需要将文档中的内容进行处理然后传递回索引或者API中。
例如,您可以使用管道来移除字段、从文本中提取值以及丰富数据。
摄取节点的配置:
默认配置下所有节点都启用了ingest。因此任何一个ES节点都可以处理ingest任务。就像之前ES集群中描述的,我们可以创建一个专门处理相关业务的ingest节点。
控制节点的ingest开关在其elasticsearch.yml中的参数
## 关闭ingest
node.ingest: false
管道(pipeline)
摄取节点节点对数据的处理主要是通过管道(pipeline),在索引和请求中指定管道参数,这样ingest节点在拦截请求后就指定使用哪条管道进行处理。
创建管道
PUT _ingest/pipeline/test_pipeline
{
"description": "测试管道",
"processors": [
{
"set": {
"field": "des",
"value": "管道默认数据"
}
}
]
}
查询管道
# 查询test_pipeline管道
GET _ingest/pipeline/test_pipeline
# 查询全部管道
GET _ingest/pipeline/*
删除管道
DELETE _ingest/pipeline/test_pipeline
DELETE _ingest/pipeline/*
使用管道
创建索引:
PUT index10
{
"settings": {
"number_of_shards": 1,
"number_of_replicas": 0
},
"mappings": {
"properties": {
"id":{
"type":"long"
},
"description":{
"type":"text"
},
"name":{
"properties": {
"firstname":{"type":"keyword"},
"lastname":{"type":"keyword"}
}
}
}
}
}
插入数据,使用已创建的管道
PUT index10/_doc/1?pipeline=test_pipeline
{
"id": 1,
"description": "描述1"
}
查看数据:
{
"took" : 0,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 1.0,
"hits" : [
{
"_index" : "index10",
"_type" : "_doc",
"_id" : "1",
"_score" : 1.0,
"_source" : {
"des" : "管道默认数据",
"description" : "描述1",
"id" : 1
}
}
]
}
}
会发现其des内容并非我们插入的数据,而是管道设置的参数。
从上面的内容可以发现,管道其实很像是我们平时使用的拦截器操作,会拦截一些操作然后对其进行修改。
模拟管道
GET _ingest/pipeline/_simulate
{
"pipeline" :
{
"description": "_description",
"processors": [
{
"set" : {
"field" : "field2",
"value" : "_value"
}
}
]
},
"docs": [
{
"_source": {
"foo": "bar"
}
},
{
"_source": {
"foo": "rab"
}
}
]
}
结果:
{
"docs" : [
{
"doc" : {
"_index" : "_index",
"_type" : "_doc",
"_id" : "_id",
"_source" : {
"field2" : "_value",
"foo" : "bar"
},
"_ingest" : {
"timestamp" : "2022-02-15T08:38:42.604065Z"
}
}
},
{
"doc" : {
"_index" : "_index",
"_type" : "_doc",
"_id" : "_id",
"_source" : {
"field2" : "_value",
"foo" : "rab"
},
"_ingest" : {
"timestamp" : "2022-02-15T08:38:42.604094Z"
}
}
}
]
}
管道中对文档数据操作
操作文档数据
假如需要对文档中某些字段进行操作,只需要在field中指定字段名称或者通过_source前缀进行访问。
GET _ingest/pipeline/_simulate
{
"pipeline" :
{
"description": "_description",
"processors": [
{
"set" : {
"field" : "foo",
"value" : "foo_value"
}
},
{"set" : {
"field" : "_source.bar",
"value" : "bar_value"
}
}
]
},
"docs": [
{
"_source": {
"foo": "foo1",
"bar":"bar1"
}
},
{
"_source": {
"foo": "foo2",
"bar":"bar2"
}
}
]
}
结果可以发现使用这两个方式都可以修改对应内容。
{
"docs" : [
{
"doc" : {
"_index" : "_index",
"_type" : "_doc",
"_id" : "_id",
"_source" : {
"bar" : "bar_value",
"foo" : "foo_value"
},
"_ingest" : {
"timestamp" : "2022-02-15T08:54:16.390878Z"
}
}
},
{
"doc" : {
"_index" : "_index",
"_type" : "_doc",
"_id" : "_id",
"_source" : {
"bar" : "bar_value",
"foo" : "foo_value"
},
"_ingest" : {
"timestamp" : "2022-02-15T08:54:16.390885Z"
}
}
}
]
}
除了文档中的字段,我们也可以使用_index、_type、_id、_routing对ES的元数据进行访问。(无需担心此操作会影响文档数据,因为ES限制映射中的字段不能存在和元数据相同的字段名)
在上面例子的返回内容中可以看到有一个_ingest属性。_ingest的数据同样可以使用_ingest.timestamp来提取其时间戳。但是需要注意的是ingest元数据并不是持久的数据,其在管道处理完毕之后就被丢弃。
使用文档中的数据
有些时候我们使用管道只是进行时间戳的赋值或者字段拼接,其内容根据数据内容的变化而变化。这个时候我们需要获取到文档或者ES的元素进行操作。这个情况下我们可以使用{{field}}的方式进行访问。
获取_ingest中的时间戳赋值给received
{
"set": {
"field": "received",
"value": "{{_ingest.timestamp}}"
}
}
简单的字段拼接
{
"set": {
"field": "field_c",
"value": "{{field_a}} {{field_b}}"
}
}
动态参数设置
同样我们可以在field字段上使用{{}}使其可以根据实际数据对不同的字段进行赋值。
{
"set": {
"field": "{{service}}",
"value": "{{code}}"
}
}