Elasticsearch嵌套查询

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

一、背景

最近在做基于宴会厅档期的商户搜索推荐时,如果用传统平铺式的mapping结构,无法满足需求场景,于是用到了Elasticsearch支持的Nested(嵌套)查询。

二、普通对象与嵌套对象的索引异同

如果一个对象不是嵌套类型,那么以如下原数据为例:

PUT /my_index/blogpost/1  
{  "title":"Nest eggs",  "body":  "Making your money work...",  "tags":  [ "cash", "shares" ],  "comments":[  {  "name":    "John Smith",  "comment": "Great article",  "age":     28,  "stars":   4,  "date":    "2014-09-01"  },  {  "name":    "Alice White",  "comment": "More like this please",  "age":     31,  "stars":   5,  "date":    "2014-10-22"  }  ]  
}

由于是json格式的结构化文档,es会平整成索引内的一个简单键值格式,如下:

{  "title":  [ eggs, nest ],  "body":  [ making, money, work, your ],  "tags":    [ cash, shares ],  "comments.name":    [ alice, john, smith, white ],  "comments.comment":  [ article, great, like, more, please, this ],  "comments.age":      [ 28, 31 ],  "comments.stars":     [ 4, 5 ],  "comments.date":      [ 2014-09-01, 2014-10-22 ]  
}

这样的话,像这种john/28,Alice/31间的关联性就丢失了,Nested Object就是为了解决这个问题。

将comments指定为Nested类型,如下mapping:

curl -XPUT 'localhost:9200/my_index' -d '  
{  "mappings":{  "blogpost":{  "properties":{  "comments":{  "type":"nested",   //声明为nested类型"properties":{  "name":    {"type":"string"},  "comment": { "type": "string"},  "age":     { "type": "short"},  "stars":   { "type": "short"},  "date":    { "type": "date"}  }  }  }  }  }  
}

这样,每一个nested对象将会作为一个隐藏的单独文本建立索引,进而保持了nested对象的内在关联关系,如下:

{ ①  "comments.name":    [ john, smith ],  "comments.comment": [ article, great ],  "comments.age":     [ 28 ],  "comments.stars":   [ 4 ],  "comments.date":    [ 2014-09-01 ]  
}  
{   "comments.name":    [ alice, white ],  "comments.comment": [ like,more,please,this],  "comments.age":     [ 31 ],"comments.stars":   [ 5 ],  "comments.date":    [ 2014-10-22 ]  
}  
{   "title":          [ eggs, nest ],  "body":         [ making, money, work, your ],  "tags":          [ cash, shares ]  
}  
①nested object

三、嵌套对象的查询

命令查询(输出结果1):

curl -XGET localhost:9200/yzsshopv1/shop/_search?pretty -d '{"query" : {"bool" : {"filter" : {"nested" : {"path":"hallList","query":{"bool":{"filter":{"term":{"hallList.capacityMin" : "11"}}}}}}}}}'
{"took" : 3,"timed_out" : false,"_shards" : {"total" : 5,"successful" : 5,"failed" : 0},"hits" : {"total" : 1,"max_score" : 0.0,"hits" : [ {"_index" : "yzsshopv1","_type" : "shop","_id" : "89999988","_score" : 0.0,"_source" : {"cityId" : "1","shopName" : "xxxx婚宴(yyyy店)","shopId" : "89999988","categoryId" : [ "55", "165", "2738" ],"hallList" : [ {"hallId" : "20625","schedule" : ["2017-11-10", "2017-11-09"],"capacityMax" : 16,"capacityMin" : 12},  {"hallId" : "21080","schedule" : [ "2017-12-10", "2017-09-09",  "2017-02-25"],"capacityMax" : 20,"capacityMin" : 11} ],"wedHotelTagValue" : [ "12087", "9601", "9603", "9602" ],"regionId" : [ "9", "824" ]}} ]}
}

java api查询封装:

BoolQueryBuilder boolBuilder = new BoolQueryBuilder();
NestedQueryBuilder nestedQuery = new NestedQueryBuilder("hallList", new TermQueryBuilder("hallList.capacityMin","11"));   //注意:除path之外,fieldName也要带上path (hallList)boolBuilder.filter(nestedQuery);
searchRequest.setQuery(boolBuilder); //设置查询条件

java api输出字段封装:

searchRequest.addField("shopId");
searchRequest.addField("hallList. schedule");
searchRequest.addField("hallList.capacityMin");
searchRequest.addField("hallList.capacityMax");

如果输出的outputField为searchRequest.addField("hallList"),则会报错:illegal_argument_exception,reason:field [hallList] isn't a leaf field;

如果输出的outputField为searchRequest.addField("capacityMin"),则不报错,但没有capacityMin字段的值;

正确调用search后的输出结果(输出结果2):

{"took" : 8,"timed_out" : false,"_shards" : {"total" : 5,"successful" : 5,"failed" : 0},"hits" : {"total" : 1,"max_score" : 0.0,"hits" : [{"_index" : "yzsshopv1","_type" : "shop","_id" : "89999988","_score" : 0.0,"fields" : {"shopId" : [ "89999988" ],"hallList.hallId" : [ "20625", "21080"],"hallList.capacityMin" : [12, 11 ],"hallList.capacityMax" : [16, 20 ],"hallList.schedule" : [ "2017-11-10", "2017-11-09",  "2017-12-10", "2017-09-09",  "2017-02-25"]}}]}
}

对比输出结果1和2发现,命令输出嵌套对象结果1没问题,但通过java api输出结果2时,嵌套对象内部的关系也会打乱,比如hallList.schedule字段,无法区分到底哪些值属于hallList.hallId-20625,哪些属于21080。

//============以下更新20170331===========

经过后续调试,发现要让java api输出正确结果的嵌套对象,不能通过searchRequest.addField的方式,因为嵌套对象并不是叶子节点,需要通过以下的方式添加输出字段:

searchRequest.setFetchSource(new String[]{"shopId","hallList"},new String[]{});

还有一个不足点是: 嵌套查询请求返回的是整个文本,而不仅是匹配的nested文本。

四、参考文档

  1. https://www.elastic.co/guide/en/elasticsearch/guide/master/nested-objects.html
  2. http://stackoverflow.com/questions/23562192/unable-to-retrieve-nested-objects-using-elasticsearch-java-api
  3. http://elasticsearch.cn/book/elasticsearch_definitive_guide_2.x/nested-aggregation.html

转载于:https://my.oschina.net/weiweiblog/blog/1572727

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

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

相关文章

如何使用PowerShell提升开发效率(以Windows Embedded CE为例)

简介 本文讲述如何使用Powershell通过RAPI来控制Windows Embedded CE和Windows Mobile设备。 缘由 我入行的时候是做AS400 RPG和UNIX C开发的,所有开发环境都是字符界面,因此习惯了vigrepmake的开发模式。后来开始做Windows的开发,开始也不大…

Windows7旗舰版磁盘分区详解—附分区步骤截图

最近工作中配置使用联想的Thinkpad TL系列本本.当然原装的系统时刚发布的Windows RTM旗舰版.在考虑买之前也参考了戴尔 苹果的等等, 但个人私下也是一直在用Tinkpad系列, 相比其他的品牌本人还是比较钟情于Tinkpad 非常实用的键盘. 以及简洁的外观.买回来一看这个TL系列原装的系…

outlook存档邮件_如何在Outlook 2013中存档电子邮件

outlook存档邮件We’ve always been told that backing up our data is a good idea. Well, that same concept can extend to email as well. You may want to archive your email every so often, such as monthly, quarterly, or even yearly. 我们一直被告知备份数据是一个…

计算机组装和维护_如何构建自己的计算机,第二部分:组装在一起

计算机组装和维护So you’ve selected your parts, double- and triple-checked their compatibility, and waited for economy shipping to bring them all to your door. It’s time to get to the fun part: putting them all together. 因此,您已经选择了零件&a…

Autofac之自动装配

从容器中的可用服务中选择一个构造函数来创造对象,这个过程叫做自动装配。这个过程是通过反射实现的 默认 思考这么一个问题,如果注册类型中存在多个构造函数,那么Autofac会选择哪一个来创建类型的实例 答案是"尽可能最多参数" class ConstructorClass {p…

对Emlog 6.0 Beta的完整代码审计过程

Emlog 6.0 beta版本,这可能是最后一篇关于PHP语言CMS的代码审计文章,此次将详细记录完整的审计过程。 文章基本上完整记录小东的对此CMS审计过程,或许显得繁琐,但代码审计的过程就是这样,发现可能项,然后精…

SINOCES 2011

突然发现又好久没写过日志了 是在是太懒了… 难得休假去看了眼消费电子 感觉实在是一年不如一年 佳能、索尼不见踪影,相机满场没见一家(大牌子是真没见到) 华硕技嘉微星等主板厂商同样失踪… PC方面,联想貌似是来卖电脑包鼠标的&a…

esim卡与ms卡的区别_什么是eSIM,它与SIM卡有何不同?

esim卡与ms卡的区别With the launch of the Apple Watch 3, the term “eSIM” has been thrown around a lot. And now, Google’s Pixel 2 is the first phone to use this new technology, it’s time we take a closer look at what it is, what it does, and what this me…

机器学习实战之logistic回归分类

利用logistic回归进行分类的主要思想:根据现有数据对分类边界建立回归公式,并以此进行分类。 logistic优缺点: 优点:计算代价不高,易于理解和实现。缺点:容易欠拟合,分类精度可能不高。 .适用数…

HDU 6343.Problem L. Graph Theory Homework-数学 (2018 Multi-University Training Contest 4 1012)

6343.Problem L. Graph Theory Homework 官方题解: 一篇写的很好的博客: HDU 6343 - Problem L. Graph Theory Homework - [(伪装成图论题的)简单数学题] 代码: 1 //1012-6343-数学2 #include<iostream>3 #include<cstdio>4 #include<cstring>5 #include<…

Android GridView LruCache

照片墙这种功能现在应该算是挺常见了&#xff0c;在很多应用中你都可以经常看到照片墙的身影。它的设计思路其实也非常简单&#xff0c;用一个GridView控件当作“墙”&#xff0c;然后随着GridView的滚动将一张张照片贴在“墙”上&#xff0c;这些照片可以是手机本地中存储的&a…

如何在Android TV上自定义推荐行

When you fire up Android TV, the first thing you see is a list of movies and shows the system thinks you’ll like. It’s often full of the latest flicks or hottest news, but sometimes it could just be things relevant to your interests and the apps you have…

steam串流到手机_如何从手机将Steam游戏下载到PC

steam串流到手机Steam allows you to remotely install games from your smartphone, just like you can with a PlayStation 4 or Xbox One. You can download games to your gaming PC from anywhere, ensuring those big downloads are complete and the game is ready to p…

禁用windows10更新_如何在Windows 10中禁用投影

禁用windows10更新The drop shadows on applications in the Windows 10 preview are really big and suspiciously similar to the ones in OS X, and if they aren’t your speed, you can easily remove them. We actually think they look good, but since somebody out th…

如何访问 Service?- 每天5分钟玩转 Docker 容器技术(99)

前面我们已经学习了如何部署 service&#xff0c;也验证了 swarm 的 failover 特性。不过截止到现在&#xff0c;有一个重要问题还没有涉及&#xff1a;如何访问 service&#xff1f;这就是本节要讨论的问题。 为了便于分析&#xff0c;我们重新部署 web_server。 ① docker se…

Linux配置手册(二)配置DHCP服务器

1.检查是否安装DHCP服务器软件 2.挂在RHEL5系统光盘 3.安装DHCP服务软件 4.将模板配置文件复制并覆盖现在的配置文件 5.配置修改dhcpd.conf文件 配置信息 默认租约时间 default-lease-time 最大租约时间 max-lease-time 局域网内所有主机的域名 option domain-name 客户机所使用…

什么是Google Play保护以及如何确保Android安全?

Android is open, flexible, and all about choice. Unfortunately, that flexibility comes more potential security issues. The good news is that Google has a system in place named Play Protect that helps keep Android secure. Android开放&#xff0c;灵活且具有多…

如何使计算机为您读取文档

Since the beginning of the computer age, people have always enjoyed making computers talk to them. These days, that functionality is built right into Windows and you can easily use it to have your PC read documents to you. 自计算机时代开始以来&#xff0c;人…

面试中常问的List去重问题,你都答对了吗?

2019独角兽企业重金招聘Python工程师标准>>> 面试中经常被问到的list如何去重&#xff0c;用来考察你对list数据结构&#xff0c;以及相关方法的掌握&#xff0c;体现你的java基础学的是否牢固。 我们大家都知道&#xff0c;set集合的特点就是没有重复的元素。如果集…

Coolite Toolkit学习笔记五:常用控件Menu和MenuPanel

Coolite Toolkit里的Menu控件和其他的.NET Web控件不一样&#xff0c;如果只是设计好了Menu或是通过程序初始化菜单项&#xff0c;菜单是不会呈现在界面上的&#xff0c;因为Coolite Toolkit规定Menu控件需要一个容器来做依托&#xff0c;而这个让Menu依托的控件就是MenuPanel&…