我正在查询~ 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选择性地将现有索引中的某些字段重新索引到新索引中。这不会非常昂贵,也不会花费时间,并且您将得到聚合的结果。