从"text field"获取不同的值,而无需重新映射



我正在查询~ 350tb的文档。

不能重新索引。

性能,在合理范围内,不是一个问题。

我的文档有一个字段s3_filename{"type": "text"}。它没有任何子字段

fielddata: true设置为s3_filename会导致错误的结果(它返回唯一的"字";从值(非唯一值)

s3_filename的值与ud20220711/long-file-name-20220711.json.gz相似

我想要值(ud20220711/long-file-name-20220711.json.gz)的聚合,然而,我得到的却是单词的聚合:

返回部分s3_filename的桶。例如,[long,file,name,20220711,json,gz],但没有ud20220711/long-file-name-20220711.json.gz

的桶我试过简单的aggs,和复合材料的aggs,但没有工作…

编辑:关于弹性的讨论co (https://discuss.elastic.co/t/get-distinct-values-from-text-field-without-remapping/309694/5) leandrojmp向我展示了我可以创建"运行时字段"。要么在索引映射中,要么在查询本身中。我使用了查询本身的运行时字段。

下面的语句正好满足了我的需求,然而,与对相同数据集的其他查询相比,查询时间要长18倍(74分钟;与重新索引350tb大约15天相比,完全可以接受)。

{
"runtime_mappings": {
"s3_filename": {
"type": "keyword"
}
},
"aggs": {
"filenames": {
"terms": {
"field": "s3_filename",
"size": 10000
}
}
}
}

问题的关键在于ES将您的字段分析为单个令牌,而不是您想要的单个值。这就是聚合不能工作的原因。

你说驯鹿是一个问题。这就排除了重建指数的可能性。但是你有没有考虑过更新此字段的映射使用multi_fields和"关键字"。映射。

解决方案1:

PUT /my-index-000001/_mapping
{
"properties": {
"s3_filename": {
"type": "text",
"fields": {
"raw": {
"type": "keyword"
}
}
}
}
}

然后可以对"s3_filename.raw"进行聚合。链接到docs: Multi Mapping Update

解决方案2:

在运行时构造一个关键字字段并对其进行聚合。

PUT my-index-000001/
{
"mappings": {
"runtime": {
"s3_keyword": {
"type": "keyword",
"script": {
"source": "emit(ctx._source['s3_filename'])"
}
}
}
}
}

现在在这个字段上聚合。这会大大降低性能。

观察

:

将field-data设置为true,需要将整个字段源加载到内存中,并且性能永远不会很好。

重新索引数据似乎是最好的选择,如果这些都不可能,仅仅因为350tb不是那么大的问题,如果用多线程完成。最后,您是否考虑过只重新索引字段"s3_filename">变成另一个指数?您可以使用/_reindex api选择性地将现有索引中的某些字段重新索引到新索引中。这不会非常昂贵,也不会花费时间,并且您将得到聚合的结果。

最新更新