热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Elasticsearch嵌套查询

2019独角兽企业重金招聘Python工程师标准一、背景最近在做基于宴会厅档期的商户搜索推荐时,如果用传统平铺式的mapping结构,无法满足需求

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/LucasZhu/blog/1494710



推荐阅读
  • 本文详细探讨了Java集合框架的使用方法及其性能特点。首先,通过关系图展示了集合接口之间的层次结构,如`Collection`接口作为对象集合的基础,其下分为`List`、`Set`和`Queue`等子接口。其中,`List`接口支持按插入顺序保存元素且允许重复,而`Set`接口则确保元素唯一性。此外,文章还深入分析了不同集合类在实际应用中的性能表现,为开发者选择合适的集合类型提供了参考依据。 ... [详细]
  • 在开发系统查询搜索功能时,需注意以下几点以提高信息检索效率:首先,在SQL语句中,每个参数占位符“?”后必须紧跟相应的参数赋值,确保参数与赋值一一对应,避免因参数不匹配导致的错误。其次,进行模糊搜索时,若用户输入通配符“%”,可能会导致全表扫描,因此需要对输入的“%”进行特殊处理或限制,以防止不必要的性能开销。此外,建议使用索引优化查询速度,并合理设计搜索逻辑,以提升用户体验。 ... [详细]
  • Spring Boot 实战(一):基础的CRUD操作详解
    在《Spring Boot 实战(一)》中,详细介绍了基础的CRUD操作,涵盖创建、读取、更新和删除等核心功能,适合初学者快速掌握Spring Boot框架的应用开发技巧。 ... [详细]
  • 本项目在Java Maven框架下,利用POI库实现了Excel数据的高效导入与导出功能。通过优化数据处理流程,提升了数据操作的性能和稳定性。项目已发布至GitHub,当前最新版本为0.0.5。该项目不仅适用于小型应用,也可扩展用于大型企业级系统,提供了灵活的数据管理解决方案。GitHub地址:https://github.com/83945105/holygrail,Maven坐标:`com.github.83945105:holygrail:0.0.5`。 ... [详细]
  • 在C#和ASP.NET开发中,TypeParse 是一个非常实用的类型解析扩展方法库,提供了简便的类型转换功能。例如,通过 `var int1 = "12".TryToInt();` 可以将字符串安全地转换为整数,如果转换失败则返回0。此外,还支持更多复杂的类型转换场景,如 `var int2 = "22x".TryToInt();` 和 `var int3 = "3.14".TryToInt();`,确保了代码的健壮性和易用性。 ... [详细]
  • 本文将深入探讨FastJSON的基础解析机制与自定义JSON处理技巧。通过详细分析FastJSON的核心功能和高级用法,帮助读者掌握高效、灵活的JSON数据处理方法。文中还将分享一些实用的代码示例和最佳实践,助力开发者在实际项目中更好地应用FastJSON。 ... [详细]
  • 如何使用 net.sf.extjwnl.data.Word 类及其代码示例详解 ... [详细]
  • 通过优化模板消息机制,本研究提出了一种高效的信息化推送方案。该方案利用获取的访问令牌(access token)和指定的模板ID,实现了精准且快速的信息推送,显著提升了用户体验和信息传递效率。具体实现中,通过调用相关API接口,确保了消息的准确性和及时性,为用户提供更加便捷的服务。 ... [详细]
  • PHP中元素的计量单位是什么? ... [详细]
  • 开发心得:深入探讨Servlet、Dubbo与MyBatis中的责任链模式应用
    开发心得:深入探讨Servlet、Dubbo与MyBatis中的责任链模式应用 ... [详细]
  • 深入解析JWT的实现与应用
    本文深入探讨了JSON Web Token (JWT) 的实现机制及其应用场景。JWT 是一种基于 RFC 7519 标准的开放性认证协议,用于在各方之间安全地传输信息。文章详细分析了 JWT 的结构、生成和验证过程,并讨论了其在现代 Web 应用中的实际应用案例,为开发者提供了全面的理解和实践指导。 ... [详细]
  • 本文介绍了使用 Python 编程语言高效抓取微博文本和动态网页图像数据的方法。通过详细的示例代码,展示了如何利用爬虫技术获取微博内容和动态图片,为数据采集和分析提供了实用的技术支持。对于对网络数据抓取感兴趣的读者,本文具有较高的参考价值。 ... [详细]
  • Jedis接口分类详解与应用指南
    本文详细解析了Jedis接口的分类及其应用指南,重点介绍了字符串数据类型(String)的接口功能。作为Redis中最基本的数据存储形式,字符串类型支持多种操作,如设置、获取和更新键值对等,适用于广泛的应用场景。 ... [详细]
  • MVVM架构~mvc,mvp,mvvm大话开篇
    返回目录百度百科的定义:MVP是从经典的模式MVC演变而来,它们的基本思想有相通的地方:ControllerPresenter负责逻辑的处理,Model提供数据,View负责显示。作为一种新的模 ... [详细]
  • 探索JavaScript倒计时功能的三种高效实现方法及代码示例 ... [详细]
author-avatar
挤牙膏--
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有