一起来学ES —— 浅谈Nested结构

Nested是什么?

  • 直观的说,Nested实际上就是Object的数组。如下,这个user就是个nested结构
    {
    "user" : [ {"first" : "John","last" :  "Smith"},{"first" : "Alice","last" :  "White"}
    ]
    }
    

Nested 和 Object 是什么关系?

  • ES原生支持Object类型,也就是任意字段都可以是个对象,而ES又是所有字段都是多值,也就是都可以是list。那么在ES中Nested和Object List又是什么关系呢?
  • 这就要从Object说起了。Object虽然是个对象,但是实际存储时是在当前文档里打平存储的。如上那个例子,如果只有一个user,那么在真实索引中实际上是下面这样的
{"user.first" : "John","user.last" : "Smith"
}
  • 而如果是个list,那么就成了
{"user.first" : ["John","Alice"],"user.last" : ["Smith","White"]
}
  • 因为建索引时打平,因此检索时ES就无法知道到底是John Smith还是John White了。因此引入了Nested结构。
  • Nested将list里的每个doc单独变成子文档进行存储,因此在查询时就可以知道具体的结构信息了。

Nested 查询要注意什么?

  • Nested因为是单独的子文档存储,因此在使用时,直接用 a.b.c 是无法访问的,需要将其套在nested查询里。除此之外,和其他的查询并无差异。
{"query": {"nested": {"path": "user","query": {"match": {"user.first" : "John"}},"inner_hits": {}}}
}
  • 如上所示,用一个nested套住真实query即可。默认的hit是返回父文档,也就是大的doc。如果加上inner_hits会在父文档的source中多一个inner_hits的字段,返回真实命中的object,其中有个offset表明list数组下标。
  • 需要注意的是,由于单独存储很耗资源,因此默认一个index最多只有50个nested字段。此外,虽然nested是单独存储的,但是其字段数也算入index总字段数,默认最多1000个。

Nested Aggregation是什么?

  • 对于Nested结构,有一点需要谨记的,就是他是个List结构。Nested Agg就是对这个list做agg操作,agg写法和普通的一样,只需要在外面套上nested即可。
  • 如官方文档的例子,就是一个商品有许多卖家,对这些卖家的报价求最小值。

能否用Nested做动态kv?

  • Nested除了存储固定的Object List,还有一种常用的场景就是用来存储动态的KV。虽然ES天然支持dynamic mapping,但是其key都是固化在每一个doc中的,如果存储用户自定义报表数据。每个用户的key差异很大,放在同一张表会出现大量空值。这是很浪费系统资源的行为,并且随着Key的不断增多,最终会超出index的最大key数量。
  • 因此用nested结构来处理这种动态kv就比较合适。 nested的本质就是将 {"tags":{"k1":"v1","k2":"v2"}}=>{"tags":[{"key":"key1","value":"v1"},{"key":"key2","value":"v2"}]}
  • 这样一来就可以轻松处理动态kv。并且查询依旧简单,例如k1:v1 AND k2:v2变为
{"query": {"bool": {"must": [{"nested": {"path": "tags","query": {"query_string": {"query": "tags.key:k1 AND tags.value:v1"}}}},{"nested": {"path": "tags","query": {"query_string": {"query": "tags.key:k2 AND tags.value:v2"}}}}]}}
}

动态kv如何做agg呢?

  • 普通查询的确很简单,但是agg就并不简单了。原来的模式可以直接用真实字段tags.k1做agg,但是在nested里k1已经变成了一个字段的值,因此没法直接做agg了。
  • 这时就需要引入script大法了。其实agg的本质就是从每个doc的正排里取一个值,用这个值做聚合。因此我们只需要用script遍历list,找到对应的key然后返回其value即可。
  • 简单写了个如下所示,如果有更好的方法欢迎留言。
  • 注意!!! 由于nested单独存储,因此doc里并没有nested数据,需要用params从source中拿。性能很差,仅可用于少量数据场景!
{ ..."aggs": {"test_agg": {"terms": {"script": {"inline": "for(int i=0;i<params['_source']['tags'].length;i++){if(params['_source']['tags'][i]['key']=='k1'){return params['_source']['tags'][i]['value']}}","lang": "painless"},"size": 5}}}
}
  • 在使用中我们还可以把script存在来,来加速运算,减少缓存。(注意:5.6以后将code改为了source字段,具体写法参阅文档)
POST _scripts/is_tag_key
{"script":{"lang": "painless","code":"for(int i=0;i<params['_source']['tags'].length;i++){if(params['_source']['tags'][i]['key']==params.key){return params['_source']['tags'][i]['value']}}"}
}
  • 这样用起来就简单多了
{ ..."aggs": {"test_agg": {"terms": {"script": {"stored": "is_tag_key","params": {"key": "k1"}},"size": 5}}}
}

怎么在kibana里做agg呢?

  • kibana其实和上面的一样,也是用script.不过只支持inline的,在script field配置。不过注意一定不能太多,因为每一个inline script都是一个单独的script都需要消耗存储资源。

参考资料

  • nested datatype
  • nested query
  • nested agg
  • How to use scripts
  • painless DEBUG

版权声明

  • 自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)
  • 本文首发于: http://czjxy881.coding.me/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/330420.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

并集查经典(转发)

首先在地图上给你若干个城镇&#xff0c;这些城镇都可以看作点&#xff0c;然后告诉你哪些对城镇之间是有道路直接相连的。最后要解决的是整幅图的连通性问题。比如随意给你两个点&#xff0c;让你判断它们是否连通&#xff0c;或者问你整幅图一共有几个连通分支&#xff0c;也…

关于es查询dsl的filter与must,term与match的区别

【1】创建es7 索引 put localhost:9200/pdi_cust &#xff0c; 注意 PUB_CUST_LABEL 字段分词了。 es7 不支持type &#xff0c;所以 无需指定type。 { "mappings" :{ "properties":{"RCRD_ID":{"type":"keyword"…

高级Java必看的10本书

转载自 高级Java必看的10本书 1、深入理解Java虚拟机&#xff1a;JVM高级特性与最佳实践 本书共分为五大部分&#xff0c;围绕内存管理、执行子系统、程序编译与优化、高效并发等核心主题对JVM进行了全面而深入的分析&#xff0c;深刻揭示了JVM的工作原理。 2、从Paxos到Zookee…

ES嵌套聚合

【1】 // dsl {"_source":["RCRD_ID", "STATE", "BUSI_CODE"], "query":{"bool":{"filter":[{"term":{"STATE":"PDOS"} }, {"nested":{"path":…

进阶Java架构师必看的15本书

转载自 进阶Java架构师必看的15本书 1、大型网站技术架构&#xff1a;核心原理与案例分析 本书通过梳理大型网站技术发展历程&#xff0c;剖析大型网站技术架构模式&#xff0c;深入讲述大型互联网架构设计的核心原理&#xff0c;并通过一组典型网站技术架构设计案例&#xff0…

HDU2612(BFS算法)

Problem Descrption Pass a year learning in Hangzhou, yifenfei arrival hometown Ningbo at finally. Leave Ningbo one year, yifenfei have many people to meet. Especially a good friend Merceki. Yifenfei’s home is at the countryside, but Merceki’s home is in…

es 嵌套类型聚合

【1】分组后求均值聚合 //dsl {"_source":["RCRD_ID", "STATE", "BUSI_CODE"], "query":{"bool":{"filter":[{"term":{"STATE":"PDOS"} }]} }, "aggs"…

2017年,Java程序猿10本经典好书推荐

1、Java 8实战 本书全面介绍了Java 8 这个里程碑版本的新特性&#xff0c;包括Lambdas、流和函数式编程。有了函数式的编程特性&#xff0c;可以让代码更简洁&#xff0c;同时也能自动化地利用多核硬件。全书分四个部分&#xff1a;基础知识、函数式数据处理、高效Java 8 编程和…

es嵌套聚合dsl(求均值,求和)

【1】根据客户号分组后求均值和求和 // dsl {"_source":["RCRD_ID", "STATE", "BUSI_CODE"], "query":{"bool":{"filter":[{"term":{"STATE":"PDOS"} }]} }, &…

字符串拼接+和concat的区别

转载自 字符串拼接和concat的区别和concat都可以用来拼接字符串&#xff0c;但在使用上有什么区别呢&#xff0c;先来看看这个例子。 public static void main(String[] args) {// example1String str1 "s1";System.out.println(str1 100);//s1100System.out.prin…

thinking-in-java(21)并发2

think-in-java 并发前半部分&#xff08;并发1&#xff09;参见&#xff1a; https://blog.csdn.net/PacosonSWJTU/article/details/104855730 【21.4.3】中断 1、Thread类包含 interrupt方法&#xff0c;可以终止被阻塞的任务。这个方法将设置线程的中断状态。 如果一个线程…

HDU1176(DP)

Problem Description 都说天上不会掉馅饼&#xff0c;但有一天gameboy正走在回家的小径上&#xff0c;忽然天上掉下大把大把的馅饼。说来gameboy的人品实在是太好了&#xff0c;这馅饼别处都不掉&#xff0c;就掉落在他身旁的10米范围内。馅饼如果掉在了地上当然就不能吃了&am…

Java趣味分享:try/finally

转载自 Java趣味分享&#xff1a;try/finally考虑以下四个测试方法&#xff0c;它们会输出什么&#xff1f;public class Test {public static void main(String[] args) {System.out.println(test1());System.out.println(test2());System.out.println(test3());System.out.pr…

(转)ThreadPoolExecutor最佳实践--如何选择队列

转自&#xff1a; https://blog.hufeifei.cn/2018/08/12/Java/ThreadPoolExecutor%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5--%E5%A6%82%E4%BD%95%E9%80%89%E6%8B%A9%E9%98%9F%E5%88%97/ 前一篇文章《如何选择线程数》讲了如何决定线程池中线程个数&#xff0c;这篇文章讨论“如何…

HDU1576(欧几里得算法)

Problem Descption 要求(A/B)%9973&#xff0c;但由于A很大&#xff0c;我们只给出n(nA%9973)(我们给定的A必能被B整除&#xff0c;且gcd(B,9973) 1)。 Input 数据的第一行是一个T&#xff0c;表示有T组数据。 每组数据有两个数n(0 < n < 9973)和B(1 < B < 10^…

为什么byte取值-128~127??

转载自 为什么byte取值-128~127??java设计byte类型为1个字节&#xff0c;1个字节占8位&#xff0c;即8bit&#xff0c;这是常识。另外&#xff0c;计算机系统中是用补码来存储的&#xff0c;首位为0表示正数&#xff0c;首位为1表示负数&#xff0c;所以有以下结论&#xff1…

(转)threadPoolExecutor 中的 shutdown() 、 shutdownNow() 、 awaitTermination() 的用法和区别

最近在看并发编程&#xff0c;在使用到ThreadPoolExecutor时&#xff0c;对它的三个关闭方法&#xff08;shutdown()、shutdownNow()、awaitTermination()&#xff09;产生了兴趣&#xff0c;同时又感到迷惑。查了些资料&#xff0c;自己写了测试代码&#xff0c;总算有了个比较…

HDU2049(错列排序)

国庆期间,省城HZ刚刚举行了一场盛大的集体婚礼,为了使婚礼进行的丰富一些,司仪临时想出了有一个有意思的节目,叫做"考新郎",具体的操作是这样的: 首先,给每位新娘打扮得几乎一模一样,并盖上大大的红盖头随机坐成一排; 然后,让各位新郎寻找自己的新娘.每人只准找一个,…

厉害了,Servlet3的异步处理机制

转载自 厉害了&#xff0c;Servlet3的异步处理机制Servlet3发布好几年了&#xff0c;又有多少人知道它的新特性呢&#xff1f;下面简单介绍下。 主要增加了以下特性&#xff1a; 1、异步处理支持 2、可插性支持 3、注解支持&#xff0c;零配置&#xff0c;可不用配置web.xml ..…

(转)Elasticsearch 聚合查询、桶聚合、管道聚合及复合查询

转自&#xff1a; https://blog.csdn.net/zx711166/article/details/81906881 聚合查询 聚合是一种基于查询条件对数据进行分桶、计算的方法。 聚合可以嵌套&#xff0c;由此可以组合复杂的操作&#xff08;Bucketing 聚合可以包含 sub-aggregation&#xff09;。 聚合的三种…