我在elasticsearch(5.5.1)中有一个字段,我需要重命名,因为名称包含'。'它引起了各种各样的问题。我想重命名的字段嵌套在另一个字段中。
我正在尝试使用Ingest管道中的重命名处理器来执行Reindex,如下所述:https://stackoverflow.com/a/43142634/5114
这是我的管道模拟请求(您可以将其逐字复制到Kibana的Dev Tools实用程序中进行测试):
POST _ingest/pipeline/_simulate
{
"pipeline" : {
"description": "rename nested fields to remove dot",
"processors": [
{
"rename" : {
"field" : "message.message.group1",
"target_field" : "message_group1"
}
},
{
"rename" : {
"field" : "message.message.group2",
"target_field" : "message.message_group2"
}
}
]
},
"docs":[
{
"_type": "status",
"_id": "1509533940000-m1-bfd7183bf036bd346a0bcf2540c05a70fbc4d69e",
"_version": 5,
"_score": null,
"_source": {
"message": {
"_job-id": "AV8wHJEaa4J0sFOfcZI5",
"message.group1": 0,
"message.group2": "foo"
},
"timestamp": 1509533940000
}
}
]
}
问题是我在尝试使用我的管道时遇到错误:
{
"docs": [
{
"error": {
"root_cause": [
{
"type": "exception",
"reason": "java.lang.IllegalArgumentException: java.lang.IllegalArgumentException: field [message.message.group1] doesn't exist",
"header": {
"processor_type": "rename"
}
}
],
"type": "exception",
"reason": "java.lang.IllegalArgumentException: java.lang.IllegalArgumentException: field [message.message.group1] doesn't exist",
"caused_by": {
"type": "illegal_argument_exception",
"reason": "java.lang.IllegalArgumentException: field [message.message.group1] doesn't exist",
"caused_by": {
"type": "illegal_argument_exception",
"reason": "field [message.message.group1] doesn't exist"
}
},
"header": {
"processor_type": "rename"
}
}
}
]
}
我认为问题是由字段“message.group1”在另一个字段(“message”)中引起的。我不确定如何在处理器的上下文中引用我想要的字段。似乎嵌套字段,包含点的字段和包含点的嵌套字段之间可能存在歧义。
我正在寻找引用这些字段的正确方法,或者如果Elasticsearch无法做到我想要的,请确认这是不可能的。如果Elasticsearch可以做到这一点,那么它可能会非常快,否则我必须编写一个外部脚本来提取文档,转换它们,然后将它们重新保存到新索引中。
答案 0 :(得分:1)
好的,调查Elasticsearch代码,我想我知道为什么这不起作用。
首先我们来看看Elasticsearch重命名处理器: https://github.com/elastic/elasticsearch/blob/9eff18374d68355f6acb58940a796268c9b6f2de/modules/ingest-common/src/main/java/org/elasticsearch/ingest/common/RenameProcessor.java#L76-L84
Object value = document.getFieldValue(field, Object.class);
document.removeField(field);
try {
document.setFieldValue(targetField, value);
} catch (Exception e) {
// setting the value back to the original field shouldn't as we just fetched it from that field:
document.setFieldValue(field, value);
throw e;
}
这是在寻找要重命名的字段,获取其值,然后删除字段并添加具有相同值但具有新名称的新字段。
现在我们来看看document.getFieldValue中会发生什么: https://github.com/elastic/elasticsearch/blob/9eff18374d68355f6acb58940a796268c9b6f2de/core/src/main/java/org/elasticsearch/ingest/IngestDocument.java#L101-L108
public <T> T getFieldValue(String path, Class<T> clazz) {
FieldPath fieldPath = new FieldPath(path);
Object context = fieldPath.initialContext;
for (String pathElement : fieldPath.pathElements) {
context = resolve(pathElement, path, context);
}
return cast(path, context, clazz);
}
请注意,它使用FieldPath对象来表示文档中字段的路径。
现在看看FieldPath如何表示路径: https://github.com/elastic/elasticsearch/blob/9eff18374d68355f6acb58940a796268c9b6f2de/core/src/main/java/org/elasticsearch/ingest/IngestDocument.java#L688
this.pathElements = newPath.split("\\.");
这是在任何“。”上分割路径。 character,因为这是字段名称中路径元素之间的分隔符。
问题是源文档有一个名为“message.group1”的字段,所以我们需要能够引用它。只需将路径拆分为“。”不考虑包含“。”的字段名称。在名字里。我们需要一个更像javascript的语法,我们可以使用括号和引号使点表示不同的内容。
如果源文档全部转换为“。”在字段名称中将保存之前将该字段转换为对象,然后此路径方案将起作用。但是源文档的字段名称包含“。”。我们不能在某些情况下引用它们。
为了解决我的问题并重新索引我的索引,我写了一个python脚本,它提取了一批文件,转换它们并将它们批量插入到一个新索引中。这基本上是Elasticsearch reindex api所做的,但我在python中做到了。
答案 1 :(得分:0)
两年多以后,我遇到了同样的问题。您可以使用dot_expander处理器设法将点属性扩展为实际的嵌套对象。
将带点的字段扩展为对象字段。该处理器允许管道中的其他处理器可以访问名称中带有点的字段。否则,任何处理器都无法访问这些字段
This issue为我指明了正确的方向。