Elastic search中使用nested类型的内嵌对象
在大数据的应用环境中,往往使用反范式设计来提高读写性能。
假设我们有个类似简书的系统,系统里有文章,用户也可以对文章进行赞赏。在关系型数据库中,如果按照数据库范式设计,需要两张表:一张文章表和一张赞赏历史记录表,赞赏历史记录表包括了赞赏者姓名和赞赏金额。
在Elastic search中,由于都是json格式存储,则可以在一个index存储系统中的文章及其赞赏记录,这种情况下需要在elastic search中使用nested类型的内嵌对象。因为如果使用数组或者object对象的话,赞赏者姓名和赞赏金额是相互独立的进行存储,不能被正确的关联。
建立index
PUT articles
{
"mappings": {
"doc": {
"properties": {
"payment": {
"type": "nested",
"properties": {
"amount": {
"type": "integer"
},
"name": {
"type": "keyword"
}
}
}
}
}
}
}
这样articles就有了payment这个nested类型的字段,payment里面的对象有amount和name,表示金额和姓名。
产生数据
产生如下数据,表示jack给文章1赞赏了29元,ross给文章1赞赏30元,ross给文章2赞赏31元。
POST articles/doc/1
{
"payment": [
{
"name": "jack",
"amount": 29
},
{
"name": "ross",
"amount": 30
}
]
}
POST articles/doc/2
{
"payment": [
{
"name": "ross",
"amount": 31
}
]
}
根据内嵌对象进行查询
现在想查询ross赞赏过的文章,需要使用nested query
GET articles/_search
{
"query": {
"nested": {
"path": "payment",
"query": {
"term": {
"payment.name": {
"value": "ross"
}
}
}
}
}
}
path表示了nested字段的名称,需要注意的是,查询语句中要指定查询字段的全名,所以赞赏者姓名要用"payment.name"
如果在多个index上进行nested查询,没有nested字段的index会报错,这时可以将ignore_unmapped设置为true
nested对象聚合
如果想查看赞赏的平均金额,需要用nested aggregation
GET articles/_search
{
"size": 0,
"aggs": {
"nested": {
"nested": {
"path": "payment"
},
"aggs": {
"amount_avg": {
"avg": {
"field": "payment.amount"
}
}
}
}
}
}
同样注意要用path指定字段名称。返回的数据中,比普通的聚合查询多了一层嵌套
返回结果为
{
"took": 1,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 2,
"max_score": 0,
"hits": []
},
"aggregations": {
"nested": {
"doc_count": 3,
"amount_avg": {
"value": 30
}
}
}
}
nested对象聚合和过滤
如果想看ross赞赏过的总金额,一开始写出query如下
GET articles/_search
{
"size": 0,
"query": {
"nested": {
"path": "payment",
"query": {
"term": {
"payment.name": {
"value": "ross"
}
}
}
}
},
"aggs": {
"nested": {
"nested": {
"path": "payment"
},
"aggs": {
"sum": {
"sum": {
"field": "payment.amount"
}
}
}
}
}
}
此时结果并不是正确的,因为上面的query过滤的是ross赞赏过的文章,下面的聚合操作sum的是文章里所有的赞赏,包括了jack的赞赏。
所以需要在sum聚合操作之前,需要用Filter Aggregation筛选ross的赞赏。
GET articles/_search
{
"size": 0,
"query": {
"nested": {
"path": "payment",
"query": {
"term": {
"payment.name": {
"value": "ross"
}
}
}
}
},
"aggs": {
"payment": {
"nested": {
"path": "payment"
},
"aggs": {
"payer": {
"filter": {
"term": {
"payment.name": {
"value": "ross"
}
}
},
"aggs": {
"sum": {
"sum": {
"field": "payment.amount"
}
}
}
}
}
}
}
}
最外层的query筛选出ross赞赏过的文章。
第一层的aggs表示进行内嵌聚合。
第二层的aggs用Filter Aggregation筛选出表示ross赞赏行为的nested对象。
第三层的aggs进行聚合。
作者:大神带我来搬砖
链接:https://www.jianshu.com/p/d685b7b6c9d1
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
Elastic search中使用nested类型的内嵌对象的更多相关文章
- freemarker 中可以直接使用的内置对象
freemarker 中可以直接使用的内置对象 需要配置一下:springboot中配置 ## Freemarker \u914D\u7F6E ## \u6587\u4EF6\u914D\u7F6E\ ...
- 关于js函数解释(包括内嵌,对象等)
常用写法: function add(a,b) { return a + b; } alert(add(1,2)); // 结果 3 当我们这么定义函数的时候,函数内容会被编译(但不会立即执行,除非我 ...
- elastic search 日期为string类型导致视图无法展示时间的解决办法
尝试将结构化的json数据发送到es(elastic search)上,然后创建视图,这样就能以小时维度查看数据,直接使用post发送到es后,创建索引,结果提示 没有date类型的字段(field) ...
- Elastic Search中Document的CRUD操作
一. 新增Document在索引中增加文档.在index中增加document.ES有自动识别机制.如果增加的document对应的index不存在.自动创建,如果index存在,type不存在自动创 ...
- Elastic Search中filter的理解
在ES中,请求一旦发起,ES服务器是按照请求参数的顺序依次执行具体的搜索过滤逻辑的.如何定制请求体中的搜索过滤条件顺序,是一个经验活.类似query(指search中的query请求参数),也是搜索的 ...
- Elastic Search中mapping的问题
Mapping在ES中是非常重要的一个概念.决定了一个index中的field使用什么数据格式存储,使用什么分词器解析,是否有子字段,是否需要copy to其他字段等.Mapping决定了index中 ...
- JSP中的Java代码和内置对象
一.JSP中的Java代码 (一)JSP页面中有三种方式嵌入java代码: 1.java的表达式 格式:<%= java表达式 %> 2.java的语句 格式:<% java语句&g ...
- Word中高效输入公式:内嵌公式和Mathtype
Word中高效输入公式:内嵌公式和Mathtype 前言:对于理工科学生而言,公式输入必不可缺.LaTeX相比Word,在公式输入及排版方面更强大.但是对于轻量级的任务,用Word而言更加轻便(起码不 ...
- js之数据类型(对象类型——单体内置对象——Math)
Math是一个内置对象,它具有数学常数和函数的属性和方法.Math对象用于执行数学任务,和其它对象不同,Math只是一个静态对象并没有Math()构造函数,实际上,Math()只是一个由js设置的对象 ...
随机推荐
- java8学习之流的短路与并发流
并发流: 从api的角度来看,其实跟咱们之前一直在用的stream()方式差不多,但是底层是有明显的不同,所以这里初步先对并发流有一个基本的认识, 说到串行与并行,最直观的感受就是效率的不同,所以下面 ...
- LIS 普及题
题意 给你一个长度为 \(n\) 的序列 \(a\). 问是否存在一个长度为 \(L\) 的上升子序列,即存在 \(\{x_1,x_2,...,x_L\}(x_1\lt x_2\lt ...\lt x ...
- uestc summer training #1
A 一个很好想的dp ll dp[maxn][]; int main() { scanf("%d%d",&n,&k); memset(dp,,sizeof(dp)) ...
- k8sService资源
一.service资源及其实现模型 通过规则定义出由多个pod对象组合而成的逻辑集合,以及访问这组pod的策略.service关联pod资源的规则要借助于标签选择器来完成 1.service资源概述 ...
- windows2012 下面php7.2 安装mongodb4.0.4的扩展以及操作mongodb的方法
php连接mongodb驱动 的下载页面http://pecl.php.net/package/mongodb 数据插入: $manager = new MongoDB\Driver\Manager( ...
- 【JZOJ5430】【NOIP2017提高A组集训10.27】图
题目 有一个n个点的无向图,给出m条边,每条边的信息形如\(<x,y,c,r>\) 给出q组询问形如\(<u,v,l,r>\) 接下来解释询问以及边的意义 询问表示,一开始你在 ...
- (转载)搜索引擎的Query自动纠错技术和架构详解
from http://www.52nlp.cn/%E8%BE%BE%E8%A7%82%E6%95%B0%E6%8D%AE%E6%90%9C%E7%B4%A2%E5%BC%95%E6%93%8E%E7 ...
- PLT hook笔记
1. hook技术概述 hook技术是一种拦截用户函数调用的技术.通过hook技术可以实现统计用户对某些函数的调用次数,对函数注入新的功能的目标.在Linux平台,Hook技术可以分成用户和内核 ...
- 一组相关联的问题:“sudo: unable to resolve host ###: Connection timed out”、软件启动速度超慢、IPv6无法使用
造冰箱的大熊猫@cnblogs 2018/9/15 近日陆续发现计算机出现几个问题,最终发现这些问题实际上是由同一个原因导致的 问题1:无法使用IPv6 问题2:无论是启动Emacs GUI还是在命令 ...
- 排序(sort)
1.定义 排序 所谓排序,就是要整理文件中的记录,使之按关键字递增(或递减)次序排列起来.其确切定义如下: 输入:n个记录R1,R2,…,Rn,其相应的关键字分别为K1,K2,…,Kn. 输出:Ril ...