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}}"
  }
}
posted @ 2022-02-12 08:09  .Neterr  阅读(1654)  评论(0编辑  收藏  举报