我们使用 enrich processor 来简化数据的摄取。简单地说:你可以使用 enrich processor 在 ingest 期间将现有索引中的数据添加到传入文档中。比如,你可以在如下的场景中用到:
- 根据已知的 IP 地址识别 Web 服务或供应商
- 根据产品 ID 将产品信息添加到零售订单
- 根据电子邮件地址补充联系信息
- 根据用户坐标添加邮政编码
在我之前的一篇文章 “Logstash:运用jdbc_streaming来丰富我们的数据” 中,我们可以使用 Logstash 运用 jdbc_streaming 来丰富我们的数据。使用7.5发行版提供的 enrich processor 可以大大地简化整个流程。
向前一直回溯至 Elasticsearch 5.0,我们在那个版本中,首次推出了“摄入管道(ingest pipeline)”,通过这种方式,用户可以在索引文档时,对文档进行处理和丰富。通过直接在Elasticsearch 中整合这一能用户可以轻松地通过 API 进行配置,很容易扩展,而且性能十分之快。多年来,我们看到这一功能得到了广泛的应用,我们目前在几乎所有模块(亦即我们提供原生支持的诸多数据源)中都调用这个功能,来进行数据的处理和丰富。无论是使用 grok 或 dissect 解析一行日志,还是为 IP 地址来添加地理位置数据,摄入管道都在逐渐成为在 Elastic Stack 中进行“摄入时处理”的主要工具。随着 7.5 的发布,我们非常兴奋地推出用户呼声最高的功能之一:基于查询结果进行丰富。通过新的 Enrich 处理器,用户能够高效 Elasticsearch 索引进行查询,并在索引时将查询结果添加到文档中。这个处理器能够使你完成很多的处理,例如根据已知的 IP 地址识别网络服务或供应商,基于用户的地理坐标添加邮编,或者从配置管理数据库(CMDB)中查询所采集主机的信息,并在索引时将相关元数据添加到文档中。
Enrich processor 在 Elastic 的免费基本订阅层下发布。
它是如何工作的?
运作方式如下:与 Elasticsearch 中的大多数内容一样,一切都始于数据。丰富处理器使用现有索引中的数据来构建查找索引。此源索引可以是诸如用户数据,地理位置数据,IP黑名单,产品数据等内容。接下来是制定丰富政策。该策略包含4个项目:类型,索引,匹配字段和填充字段。关于类型,我们今天有2种类型:match 和 geo_match。丰富处理器使用这些类型来将传入文档与存储在查找索引中的数据进行匹配。当 geo_match 使用 geo_shapes 时,Match 会针对查找索引发出术语查询。定义策略后,即可执行策略。这将基于策略中定义的索引和字段创建查找索引。最后一步是为扩充处理器创建或添加摄取管道。完成此操作后,使用此管道的传入数据将自动丰富。当新数据进入源索引时,用户始终可以通过重新运行策略来刷新查找索引。
摄取管道(ingest pipeline)会在实际建立索引之前更改文档。 你可以将摄取管线视为由一系列称为处理器的工作程序组成的装配线。 每个处理器在进入下一个文档之前,都会对传入的文档进行特定的更改,例如降低字段值的大小。 当管道中的所有处理器完成后,完成的文档将添加到目标索引。
大多数处理器是独立的,仅更改传入文档中的现有数据。 但是丰富处理器将新数据添加到传入文档中,并且需要一些特殊组件:
enrich policy
一组配置选项,用于向正确的传入文档中添加正确的扩充数据。
丰富策略包含:
- 将丰富数据存储为文档的一个或多个源索引的列表
- 决定处理器如何将丰富数据与传入文档匹配的策略类型
- 源索引中的匹配字段用于匹配传入文档
- 丰富字段,其中包含要添加到传入文档中的源索引中的扩展数据
必须先执行丰富策略,然后才能与丰富处理器(enrich processor)一起使用。 执行后,丰富策略将使用策略的源索引(source index)中的扩充数据来创建一个叫做 enrich index 的流系统索引。 处理器使用此索引来匹配和丰富传入的文档。
有丰富策略类型和配置选项的完整列表,请参阅丰富策略定义。
source index
用于存储要添加到传入文档中的丰富数据。 你可以像创建常规 Elasticsearch 索引一样创建和管理这些索引。 你可以在丰富策略中使用多个源索引。 你还可以在多个丰富策略中使用相同的源索引。
enrich index
与特定的丰富策略绑定的特定系统索引。
直接将传入文档与源索引中的文档匹配可能会很慢且占用大量资源。 为了加快处理速度,丰富处理器使用了丰富索引(enrich index)。
丰富索引(enrich index)包含来自源索引的丰富数据,但具有一些特殊属性可帮助简化它们:
- 它们是系统索引,这意味着它们由 Elasticsearch 在内部进行管理,仅适用于功能丰富的处理器。
- 它们始终以 .enrich- * 开头。
- 它们是只读的,这意味着你不能直接更改它们。
- 它们被强制合并以快速检索。
例子1:根据地理位置丰富你的数据
我们使用 geolocation 来丰富你的数据。
geo_match 丰富策略 使用 geo_shape查询 根据地理位置将丰富数据与传入文档进行匹配。
以下示例创建了 geo_match 丰富策略,该策略根据一组坐标将邮政编码添加到传入的文档中。 然后,它将 geo_match 丰富策略添加到摄取管道中的处理器。
使用 create index API 创建包含至少一个 geo_shape 字段的源索引。
PUT /postal_codes
{
"mappings": {
"properties": {
"location": {
"type": "geo_shape"
},
"postal_code": {
"type": "keyword"
}
}
}
}
这里我们首先创建一个叫做 postal_codes 的源索引的 mapping。我们使用 Index API 来创建里面的数据:
PUT /postal_codes/_doc/1?refresh=wait_for
{
"location": {
"type": "envelope",
"coordinates": [
[
13,
53
],
[
14,
52
]
]
},
"postal_code": "96598"
}
我们通过上面的命令向 postal_codes 里添加了一个文档。它其中包含 post_code 及相关的位置信息。这样我们的 soure index 就建立好了。在实际的应用中,这个 source index 的文档可能有更多。
接下来,我们来创建 enrich policy。
使用 丰富策略API 创建具有 geo_match 策略类型的丰富策略。 此策略必须包括:
- 一个或多个源索引
- match_field,来自原索引的 geo_shape 字段,用于匹配传入文档
- 丰富要添加到传入文档中的源索引中的字段
PUT /_enrich/policy/postal_policy
{
"geo_match": {
"indices": "postal_codes",
"match_field": "location",
"enrich_fields": [
"location",
"postal_code"
]
}
}
上面的策略显示,我们通过 geo_match 的方法,从源索引(source index)postal_codes 通过 location 字段来进行匹配,如果匹配,我们丰富字段 location 及 postal_code。
接着,我们使用 _execute 终点来执行 enrich policy 创建一个 enrich index。
POST /_enrich/policy/postal_policy/_execute
现在我们已经创建好了我们的 enrich index,我们可以通过 Kibana 来查看一下。我们使用如下的命令:
GET _cat/indices
在 Kibana 中我们可以看到:
我们可以看到一个以 .enrich 为开头的索引。它的内容是:
"_source" : {
"location" : {
"coordinates" : [
[
13,
53
],
[
14,
52
]
],
"type" : "envelope"
},
"postal_code" : "96598"
}
}
我们再使用 Pipleline API 来创建一个 ingest pipleline。在这个 Pipleline 中,我们来添加一个叫做 enrich 的 processor。它包括:
- 你的丰富策略
- 传入文档的字段,用于匹配来自丰富索引的文档的 geo_shape
- target_field 用于存储传入文档的附加丰富数据。 此字段包含你的丰富策略中指定的 match_field 和 rich_fields
- shape_relation,它指示处理器如何将来自丰富索引的传入文档中的 geo_shapes 与文档中的 geo_shapes 相匹配。 有关有效选项和更多信息,请参见 Spatial Relations 关系。
PUT /_ingest/pipeline/postal_lookup
{
"description": "Enrich postal codes",
"processors": [
{
"enrich": {
"policy_name": "postal_policy",
"field": "geo_location",
"target_field": "geo_data",
"shape_relation": "INTERSECTS"
}
}
]
}
使用 ingest pipeline 为文档建立索引。 传入的文档应包括你的丰富处理器(rich processor)中指定的字段。针对我们的情况是 geo_location 字段。下面我们来创建一个使用我们刚才定义的 postal_lookup pipleline 的文档:
PUT /users/_doc/0?pipeline=postal_lookup
{
"first_name": "Mardy",
"last_name": "Brown",
"geo_location": "POINT (13.5 52.5)"
}
要验证扩充处理器是否匹配并附加了适当的字段数据,请使用 get API 查看索引文档。
GET /users/_doc/0
显示结果为:
{
"_index" : "users",
"_type" : "_doc",
"_id" : "0",
"_version" : 1,
"_seq_no" : 0,
"_primary_term" : 1,
"found" : true,
"_source" : {
"geo_location" : "POINT (13.5 52.5)",
"last_name" : "Brown",
"geo_data" : {
"location" : {
"coordinates" : [
[
13,
53
],
[
14,
52
]
],
"type" : "envelope"
},
"postal_code" : "96598"
},
"first_name" : "Mardy"
}
}
如上所示,我们看到 postal_code 及 location 两个从 enrich 索引的字段添加到最终的 _source 中,并存在于 geo_data 字段中。这是因为 POINT (13.5 52.5) 正好落在我们之前定义的 .enrich 为开头的索引所定义的区域中。
例子2:根据精确值充实你的数据
匹配(match)丰富策略使用term查询,根据准确值(例如电子邮件地址或ID)将丰富数据与传入文档进行匹配。
以下示例创建一个匹配丰富策略,该策略根据电子邮件地址将用户名和联系信息添加到传入文档中。 然后,它将匹配丰富策略添加到摄取管道中的处理器。
使用创建索引 API 或索引 API 创建源索引。
以下索引API请求创建一个源索引(source index),并将一个新文档索引到该索引。
PUT /users/_doc/1?refresh=wait_for
{
"email": "mardy.brown@asciidocsmith.com",
"first_name": "Mardy",
"last_name": "Brown",
"city": "New Orleans",
"county": "Orleans",
"state": "LA",
"zip": 70116,
"web": "mardy.asciidocsmith.com"
}
使用丰富策略 API 创建具有匹配策略类型的丰富策略。 此策略必须包括:
- 一个或多个源索引
- match_field,来自源索引的字段,用于匹配传入的文档
- 丰富要添加到传入文档中的源索引中的字段
PUT /_enrich/policy/users-policy
{
"match": {
"indices": "users",
"match_field": "email",
"enrich_fields": ["first_name", "last_name", "city", "zip", "state"]
}
}
使用 execute enrich policy API 来创建一个该策略的 enrich index
POST /_enrich/policy/users-policy/_execute
使用 put pipeline API 创建摄入管道。 在管道中,添加一个丰富的处理器,其中包括:
- 你的 enrich policy。
- 传入文档字段,用于匹配富索引中的文档。
- target_field 用于存储传入文档的附加扩展数据。 此字段包含你的扩展策略中指定的 match_field 和 rich_fields。
PUT /_ingest/pipeline/user_lookup
{
"description" : "Enriching user details to messages",
"processors" : [
{
"enrich" : {
"policy_name": "users-policy",
"field" : "email",
"target_field": "user",
"max_matches": "1"
}
}
]
}
使用摄入管道为文档建立索引。 传入的文档应包括你的 rich processor 中指定的字段。
PUT /my_index/_doc/my_id?pipeline=user_lookup
{
"email": "mardy.brown@asciidocsmith.com"
}
要验证 rich processor 是否匹配并附加了适当的字段数据,请使用 get API 查看索引文档。
GET /my_index/_doc/my_id
显示的结果为:
{
"_index" : "my_index",
"_type" : "_doc",
"_id" : "my_id",
"_version" : 1,
"_seq_no" : 0,
"_primary_term" : 1,
"found" : true,
"_source" : {
"user" : {
"zip" : 70116,
"city" : "New Orleans",
"last_name" : "Brown",
"state" : "LA",
"first_name" : "Mardy",
"email" : "mardy.brown@asciidocsmith.com"
},
"email" : "mardy.brown@asciidocsmith.com"
}
}
我们可以看到 target_field 为 user,并且它包含在 enrich index 中的所需要丰富的字段:"first_name", "last_name", "city", "zip", "state"。这些字段都是在 enrich policy 中的 enrich_fields 所定义的。
参考: