ElasticSearch(ES)使用Nested结构存储KV及聚合查询

本文介绍了如何在Elasticsearch中利用nested结构解决field数量限制问题,以及如何进行查询和聚合操作。nested结构用于保持对象内部关联性,避免field数量超过限制时的错误。文中详细阐述了nested结构的定义、查询语法以及聚合方法,包括nested查询、nested聚合和多重嵌套聚合,展示了如何过滤属性值并进行有效的数据检索和分析。

自建博客地址:https://www.bytelife.net,欢迎访问! 本文为博客同步发表文章,为了更好的阅读体验,建议您移步至我的博客👇

本文作者: Jeffrey
本文链接: https://www.bytelife.net/articles/51440.html
版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!

本文将讨论如何在ElasticSearch中使用nested结构进行数据的存储、查询和聚合,并结合K-V场景讨论ElasticSearch针对field数量限制的解决方案。

为何要使用Nested结构存储KV(键值对)?

ElasticSearch对于field的数量有限制,默认情况下field的数量如果超过1000个,写入时再创建新的fields就会报错:

java.lang.IllegalArgumentException: Limit of total fields [1000] in index [(index_name)] has been exceeded
 at org.elasticsearch.index.mapper.MapperService.checkTotalFieldsLimit(MapperService.java:630)

但有些场景的field数量并不是我们能控制的,例如在监控系统中的业务数据所携带的业务标签,其中可能包含了监控系统不能预知的业务字段。
对于这种情景,可能想到的解决方案两个:

  1. 调整ElasticSearch的配置,增加field的限制数量:这种方案仅仅适用于可以预测出field数量极限的情况,治标不治本,一旦field数量再次抵达限制,又会面临同样的问题。
  2. 就是使用Pair结构来存储

假设第2种方案的数据结构为:

{
   
   
    "labels": [{
   
   
        "key": "ip",
        "value": "127.0.0.1"
     }]
},
{
   
   
    "labels": [{
   
   
        "key": "ip",
        "value": "127.0.0.2"
     }]
}

那么es查询就会存在一个问题,例如下面的查询:

{
   
   
    "query":{
   
   
        "bool":{
   
   
            "must":[
                {
   
   
                    "match":{
   
   
                        "key":"ip"
                    }
                },
                {
   
   
                    "match":{
   
   
                        "value":"127.0.0.1"
                    }
                }
            ]
        }
    }
}

这个查询会把例子中的的数据全部查询出来,并不符合我们的预期。这是因为es在存储索引时,对于普通object类型的field实际上是打平来存储的,比如这样:

{
   
   
    "labels.key":[
        "ip"
    ],
    "labels.value":[
        "127.0.0.1",
        "127.0.0.2"
    ]
}

可以看见,索引打平后,对象的关联关系丢失了。对于这种情况,ElasticSearch提供的nested结构可以帮助我们解决类似的问题。Nested结构保留了子文档数据中的关联性,如果labels的数据格式被定义为nested,那么每一个nested object将会作为一个隐藏的单独文本建立索引。如下:

{
   
   
     "labels.key":"ip",
     "labels.value":"127.0.0.1"
},
{
   
   
     "labels.key":"ip",
     "labels.value":"127.0.0.2"
}

通过分开给每个nested object建索引,object内部的字段间的关系就能保持。当执行查询时,只会匹配’match’同时出现在相同的nested object的结果。

定义mappings

使用nested结构非常简单,指定字段的type为nested即可。下面的例子中定义了一个名为labels的nested结构,其中包含两个字段,分别是key和value。

"mappings": {
   
   
    "demoType": {
   
   
        "labels": {
   
   
            // 字段类型设置为nested
            "type": "nested",
            "properties": {
   
   
                "key": {
   
   
                    "type": "keyword"
                
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值