我最近开始在弹性搜索(documentation here)中使用filtered aliases
,但有一些用例,我不知道如何处理。
使用案例
我在ElasticSearch中为一个事实索引的每个文档都将有一个名为" tenantId" (还有一些其他领域,如"类型"," id"等)。现在所有文档都驻留在同一个索引中,因此对于Tenant,我想确保创建一个过滤后的别名。现在,我想在创建租户本身后立即创建过滤后的别名,并拥有" tenantId"便利。
问题
当我尝试使用他们的Java客户端以编程方式创建别名时,我得到以下异常:
Caused by: org.elasticsearch.index.query.QueryParsingException:
[mdm-master] Strict field resolution and no field mapping
can be found for the field with name [tenantId]
研究更多,我发现我可以使用动态模板来实现这一目标。所以我创建了一个模板,将其保存在config/templates
下,重新创建了我的索引并再次尝试了同样的事情。再次得到同样的例外。在阅读文档更多here(页面底部3行)时,我发现即使我尝试将以下属性index.query.parse.allow_unmapped_fields
更改为true(我还没有尝试过) ),对于过滤的别名,它将强制它为false。
现在的问题是,我该如何处理我的用例?我不知道相应类型的映射,但我知道的事实是我索引的每个文档,无论类型如何,总是会有一个名为tenantId
的字段,这就是我想要的创建我的过滤别名。
修改
我找到了几个有用的链接。不确定修复了哪个版本。 filtered aliases in templates do not inherit mappings from aliased index #8473 index.query.parse.allow_unmapped_fields setting does not seem to allow unmapped fields in alias filters #8431
第二次编辑
发现ElasticSearch的一个开放式错误,但问题完全相同。等待ES开发人员的回复。 Failure to create Filtered Alias on empty index with template mappings #10038
非常感谢所有帮助!我一直试图从几天开始想出这个,但没有运气:(。
以下是我用来添加过滤后的别名的代码,以及默认的映射json模板
模板
{
"template-1": {
"template": "*",
"mappings": {
"_default_": {
"properties": {
"type": {
"type": "string",
"index": "not_analyzed"
},
"id": {
"type": "string",
"index": "not_analyzed"
},
"tenantId": {
"type": "string",
"index": "not_analyzed"
}
}
}
}
}
}
JAVA客户
(你现在可以忽略" Observable"相关的东西)
public Observable<Boolean> createAlias(String tenantId) {
FilterBuilder filter = FilterBuilders.termFilter("tenantId", tenantId);
ListenableActionFuture<IndicesAliasesResponse> response = client.admin().indices().prepareAliases().addAlias("mdm-master", tenantId, filter).execute();
return Observable.from(response)
.map((IndicesAliasesResponse apiResponse) -> {
return apiResponse.isAcknowledged();
});
}
答案 0 :(得分:2)
我是在ES Github上发布最新一期的人Failure to create Filtered Alias on empty index with template mappings #10038。我现在发现的最快的解决方法(除非降级到1.3,此问题不存在),是在创建别名之前使用字段索引文档。
如果您有一个包含多个租户的索引,则只需在创建索引时将文档索引一次必需字段,然后您就可以创建别名。
如果您尝试在GitHub问题中发布的复制案例,但在创建别名之前,请运行以下命令:
curl -XPOST 'http://localhost:9200/repro/dummytype/1' -d '{
"testfield": "dummyvalue"
}'
然后,您应该可以在字段testfield
上添加已过滤的别名。
编辑 - 回答第一条评论: 我认为,当您在模板中使用映射时,这是一种疏忽。创建索引时,模板将应用于匹配索引。我认为这里的问题是模板的通用映射部分实际上实际应用,直到它获得索引的文档。 如果您将问题中的模板更改为以下内容,则可以观察到此行为:
curl -XPUT 'http://localhost:9200/_template/repro' -d '{
"template": "repro",
"settings": {
"index.number_of_shards": 1,
"index.number_of_replicas": 0
},
"mappings": {
"dummytype": {
"properties": {
"testfield": {
"type": "string",
"index": "not_analyzed"
}
}
}
}
}'
然后您就可以创建索引并添加过滤后的别名,而无需索引任何文档。
正如我所说,我认为这是ES中模板应用程序中的一个错误。