ElasticSearch数据预处理

文章目录

    • [预处理节点ingest node](#预处理节点ingest node)
    • [Pipeline & Processor](#Pipeline & Processor)
    • [painless script](#painless script)

预处理节点ingest node

ES5.0版本出现的,默认配置下所有节点都是ingest node。可以对index或bulk api 请求进行拦截,对其中数据进行预处理转换,并重新返回index或bulk api。

预处理操作比如:

  • 为某个字段设置默认值
  • 重命名某个字段
  • 对字段值进行split 按某个字符进行拆分操作
  • 支持painless script脚本,对数据进行更加复杂的加工

Logstash也能对数据进行预处理操作,ingest node和Logstash最大的区别就是,ingest node是ES中的概念,只能从es的rest api请求中获取数据,并写入ES;而Logstash支持从不同的数据源读取并写入不同的数据源

Pipeline & Processor

  • pipeline,管道。会对通过的数据按照顺序进行加工。pipeline就是一组processor
  • processor,对加工的行为进行抽象包装

Elasticsearch 有很多内置的Processors,也支持通过插件的方式,实现自己的Processor。

https://www.elastic.co/guide/en/elasticsearch/reference/7.17/ingest-processors.html

一些内置的Processors:

  • Split Processor : 将给定字段值分成一个数组
  • Remove / Rename Processor :移除一个重命名字段
  • Append : 为商品增加一个新的标签
  • Convert:将商品价格,从字符串转换成float 类型
  • Date / JSON:日期格式转换,字符串转JSON对象
  • Date lndex Name Processor︰将通过该处理器的文档,分配到指定时间格式的索引中
  • Fail Processor︰一旦出现异常,该Pipeline 指定的错误信息能返回给用户
  • Foreach Process︰数组字段,数组的每个元素都会使用到一个相同的处理器
  • Grok Processor︰日志的日期格式切割
  • Gsub / Join / Split︰字符串替换│数组转字符串/字符串转数组
  • Lowercase / upcase︰大小写转换

案例,对文档中tags字段中的字符串使用逗号分隔,转换为一个数组字段

bash 复制代码
# 测试 文档中tags字段中的字符串使用逗号分隔,转换为一个数组字段
# _simulate 关键字的作用是模拟,也就是模拟查看我们预处理的结果
POST /_ingest/pipeline/_simulate
{
  "pipeline": {
    "description": "描述信息,将tags字段按逗号分隔",
    "processors": [
      {
        "split": {	# 关键字split就表示对某个字段按某个字符进行拆分  
          "field": "tags",		
          "separator": ","
        }
      }
    ]
  },
  "docs": [			# 指定两个文档数据,这些文档就要经过上面的预处理
    {
      "_index": "index",
      "_id": "1",
      "_source": {
        "title": "Introducing big data......",
        "tags": "hadoop,elasticsearch,spark",
        "content": "You konw, for big data"
      }
    },
    {
      "_index": "index",
      "_id": "2",
      "_source": {
        "title": "Introducing cloud computering",
        "tags": "openstack,k8s",
        "content": "You konw, for cloud"
      }
    }
  ]
}

案例,为文档添加一个字段

bash 复制代码
POST /_ingest/pipeline/_simulate
{
  "pipeline": {
    "description": "描述信息,将tags字段按逗号分隔",
    "processors": [
      {
        "split": {
          "field": "tags",
          "separator": ","
        }
      },
      {
        "set": {
          "field": "views",
          "value": 0
        }
      }
    ]
  },
  "docs": [
    {
      "_index": "index",
      "_id": "1",
      "_source": {
        "title": "Introducing big data......",
        "tags": "hadoop,elasticsearch,spark",
        "content": "You konw, for big data"
      }
    },
    {
      "_index": "index",
      "_id": "2",
      "_source": {
        "title": "Introducing cloud computering",
        "tags": "openstack,k8s",
        "content": "You konw, for cloud"
      }
    }
  ]
}

案例:创建pipeline

在请求的url中就不要使用_simulate模拟关键字了,直接指定一个自定义名字

bash 复制代码
# 创建一个名称为 hs_blog_pipeline 的pipeline
PUT /_ingest/pipeline/hs_blog_pipeline
{
  "description": "描述信息,将tags字段按逗号分隔",
  "processors": [
    {
      "split": {
        "field": "tags",
        "separator": ","
      }
    },
    {
      "set": {
        "field": "views",
        "value": 0
      }
    }
  ]
}

# 查看上方创建的pipeline
GET /_ingest/pipeline

使用pipeline更新数据

在url请求路径中添加pipeline=自定义pipeline名请求参数,表示当前创建的文档需要进行预处理

bash 复制代码
# 不使用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=hs_blog_pipeline
{
  "title": "Introducing cloud computering",
  "tags": "openstack,k8s",
  "content": "You konw, for cloud"
}

借助update_by_query对符合条件的文档进行更新

bash 复制代码
# 必须要POST请求
# 如果不加query查询语句会报错
POST /tech_blogs/_update_by_query?pipeline=hs_blog_pipeline
{
  
}

# 必须要POST请求
# 如果不加query查询语句会报错
# 对不存在views字段的文档进行 指定的预处理操作。此时,上方插入id=1的文档也进行了相关处理操作
POST /tech_blogs/_update_by_query?pipeline=hs_blog_pipeline
{
  "query": {
    "bool": {
      "must_not": [
        {
          "exists": {
            "field": "views"
          }
        }
      ]
    }
  }
}

painless script

painless支持所有java数据类型以及java api接口子集

用途:

  • 可以对文档字段进行加工处理

    • 更新、删除字段;处理数据聚合操作
    • 对返回的字段提前进行处理 script field
    • 对文档的相关性算分进行处理 function script
  • 在ingest pipeline中执行java脚本

  • _reindex API、_update_by_query API时对数据进行处理

通过painless script脚本访问字段

上下文 语法
Ingestion pipeline 语句中 ctx.field_name
Update 修改语句中 ctx._source.field_name
Search & Aggregation 搜索和聚合语句中 doc["field_name"]

在ingest pipeline中使用painless script

bash 复制代码
# 新增了一个script,
POST /_ingest/pipeline/_simulate
{
  "pipeline": {
    "description": "描述信息,将tags字段按逗号分隔",
    "processors": [
      {
        "split": {
          "field": "tags",
          "separator": ","
        }
      },
      {
        "set": {
          "field": "views",
          "value": 0
        }
      },
      {
        "script": {			# 使用script关键字
          "source": """		# 在source中进行java代码的编写,如果只有一条java语句就直接使用双引号,如果换行了就要在前后都加上"""三个
            if(ctx.containsKey("content")){
              ctx.hs_content_length = ctx.content.length();  #Ingestion pipeline 语句中 通过ctx.field_name语法获取文档字段
            }else{
              ctx.hs_content_length = 0;
            }
          """
        }
      }
    ]
  },
  "docs": [
    {
      "_index": "index",
      "_id": "1",
      "_source": {
        "title": "Introducing big data......",
        "tags": "hadoop,elasticsearch,spark",
        "content": "You konw, for big data"
      }
    },
    {
      "_index": "index",
      "_id": "2",
      "_source": {
        "title": "Introducing cloud computering",
        "tags": "openstack,k8s",
        "content": "You konw, for cloud"
      }
    }
  ]
}

在update语句中使用 painless script

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

# 
# 在uodate语句中,获取文档字段的方式为 ctx._source.field_name
POST /tech_blogs/_update/1
{
  "script": {
    "source": "ctx._source.views += params.new_views",		# 通过params. 的方式使用下面定义的参数
    "params": {
      "new_views": 100			# 定义一个参数
    }
  }
}


# 第二种方式,将脚本保存后再使用 hs_update_views为自定义id
POST _scripts/hs_update_views
{
  "script":{
    "lang": "painless",
    "source": "ctx._source.views += params.new_views"
  }
}

POST tech_blogs/_update/1
{
  "script": {
    "id": "hs_update_views",			# 指定上面我们自定义的id
    "params": {
      "new_views":1000
    }
  }
}

在搜索中使用painless script语句,一般不建议在搜索中使用painless script语句对字段值进行操作,这样降低了查询效率。预处理一般是新增文档时进行

bash 复制代码
GET /tech_blogs/_search
{
  "script_fields": {
    "hs_rnd_views": {
      "script": {
        "lang": "painless",
        "source": """
          java.util.Random rnd = new Random();
          doc['views'].value+rnd.nextInt(1000);
        """
      }
    }
  },
  "query": {
    "match_all": {}
  }
}
相关推荐
长风清留扬1 分钟前
一篇文章了解何为 “大数据治理“ 理论与实践
大数据·数据库·面试·数据治理
Mephisto.java1 分钟前
【大数据学习 | Spark】Spark的改变分区的算子
大数据·elasticsearch·oracle·spark·kafka·memcache
mqiqe7 分钟前
Elasticsearch 分词器
python·elasticsearch
小马爱打代码15 分钟前
Elasticsearch简介与实操
大数据·elasticsearch·搜索引擎
zhixingheyi_tian6 小时前
Spark 之 Aggregate
大数据·分布式·spark
PersistJiao6 小时前
Spark 分布式计算中网络传输和序列化的关系(一)
大数据·网络·spark
宅小海9 小时前
scala String
大数据·开发语言·scala
小白的白是白痴的白9 小时前
11.17 Scala练习:梦想清单管理
大数据
java1234_小锋9 小时前
Elasticsearch是如何实现Master选举的?
大数据·elasticsearch·搜索引擎
AiFlutter11 小时前
Java实现简单的搜索引擎
java·搜索引擎·mybatis