SpringBoot操作ES进行各种高级查询

日期:2020-03-30 10:50:43 来源:互联网 编辑:小TT 阅读人数:992

SpringBoot整合ES

<!-- ES 客户端 --> org.elasticsearch.client elasticsearch-rest-high-level-client ${elasticsearch.version}<!-- ES 版本 --> org.elasticsearch elasticsearch ${elasticsearch.version}

为容器定义 RestClient 对象

在 yml 文件中配置 eshost

yunshangxue: elasticsearch: hostlist: ${.0.0.}

调用相关 API 执行操作创建操作索引的对象

构建操作索引的请求

调用对象的相关API发送请求

获取响应

/** * 删除索引库 */@Testpublic void testDelIndex( throws IOException { // 操作索引的对象 IndicesClient indices = client.indices(; // 删除索引的请求 DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest(“ysx_course”; // 删除索引 DeleteIndexResponse response = indices.delete(deleteIndexRequest) // 得到响应 boolean b = response.isAcknowledged(; System.out.println(b)}

创建索引, 步骤和删除类似,需要注意的是删除的时候需要指定 ES 库分片的数量和副本的数量,并且在创建索引的时候可以将映射一起指定了。代码如下

public void testAddIndex throws IOException { // 操作索引的对象 IndicesClient indices = client.indices; // 创建索引的请求 CreateIndexRequest request = new CreateIndexRequest“ysx_course”; request.settingsSettings.builder.put“number_of_shards” “1”.put“number_of_replicas” “0” // 创建映射 request.mapping“doc” “{” + “ ”properties“ {” + “ ”description“ {” + “ ”type“ ”text + “ ”analyzer“ ”ik_max_word + “ ”search_analyzer“ ”ik_smart + “ },” + “ ”name“ {” + “ ”type“ ”text + “ ”analyzer“ ”ik_max_word + “ ”search_analyzer“ ”ik_smart + “ },” + pic“{ ” + typetext“ ” + index“false ” + “}, ” + “ ”price“ {” + “ ”type“ ”float + “ },” + “ ”studymodel“ {” + “ ”type“ ”keyword + “ },” + “ ”timestamp“ {” + “ ”type“ ”date + “ ”format“ ”yyyy-MM‐dd HH:mm:ssyyyy‐MM‐ddepoch_millis + “ }” + “ }” + “ }” XContentType.JSON // 执行创建操作 CreateIndexResponse response = indices.createrequest // 得到响应 boolean b = response.isAcknowledged; System.out.printlnb }

Java API操作ES

准备数据环境

创建索引:ysx_course

创建映射:

加入原始数据:

DSL搜索

DSL(Domain Specific Language)是ES提出的基于json的搜索方式,在搜索时传入特定的json格式的数据来完成不

同的搜索需求。DSL比URI搜索方式功能强大,在项目中建议使用DSL方式来完成搜索。

查询全部

原本我们想要查询全部的话,需要使用 GET 请求发送 _search 命令,如今使用 DSL 方式搜索,可以使用 POST 请求,并在请求体中设置 JSON 字符串来构建查询条件

请求体 JSON

具体的方法如下:过程比较繁琐,好在条理还比较清晰

坑:red>

执行过程中遇到的问题:不能对这个值进行初始化,导致 Spring 容器无法初始化

Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder yunshangxue.elasticsearch.hostlist in value “${yunshangxue.elasticsearch.hostlist}”

通过检查 target 目录发现,生成的 target 文件包中没有将 yml 配置文件带过来... 仔细对比发现,我的项目竟然变成了一个不是 Maven 的项目。重新使用 IDEA 导入 Mavaen 工程之后便能正常运行了

分页查询

我们来 look 一下 ES 的分页查询参数:

SpringBoot操作ES进行各种高级查询(图1)

通过查询结果可以发现,我们设置了分页参数之后, hits.total 仍然是 3,表示它找到了 3 条数据,而按照分页规则,它只会返回一条数据,因此 hits.hits 里面只有一条数据。这也符合我们的业务规则,在查询前端页面显示总共的条数和当前的数据。

由此,我们就可以通过 Java API 来构建查询条件了:对上面查询全部的代码进行如下改造:

// 搜索源构建对象SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(;int page = 2; // 页码int size = 1; // 每页显示的条数int index = (page - 1) * size;searchSourceBuilder.from(index)searchSourceBuilder.size(1)// 搜索方式// matchAllQuery搜索全部searchSourceBuilder.query(QueryBuilders.matchAllQuery

精确查询 TermQuery

Term Query为精确查询,在搜索时会整体匹配关键字,不再将关键字分词

例如:

此时查询的结果是:

查询到了上面这条数据,因为 spring基础 分完词后是 spring 基础 ,而查询关键字是 spring 不分词,这样当然可以匹配到这条记录,但是当我们修改关键字为 spring,按照往常的查询方法,也是可以查询到的。但是 term 不一样,它不会对关键字分词。结果可想而知是查询不到的

JavaAPI如下:

// 搜索方式// termQuery 精确查询searchSourceBuilder.queryQueryBuilders.termQuery“studymodel” “201002”

根据 ID 查询:

根据 ID 精确查询和根据其他条件精确查询是一样的,不同的是 id 字段前面有一个下划线注意写上

searchSourceBuilder.queryQueryBuilders.termQuery“_id” “1”

但是,当一次查询多个 ID 时,相应的 API 也应该改变,使用 termsQuery 而不是 termQuery。多了一个 s

全文检索 MatchQuery

MatchQuery 即全文检索,会对关键字进行分词后匹配词条。

query:搜索的关键字,对于英文关键字如果有多个单词则中间要用半角逗号分隔,而对于中文关键字中间可以用

逗号分隔也可以不用

operator:设置查询的结果取交集还是并集,并集用 or, 交集用 and

有时,我们需要设定一个量化的表达方式,例如查询 spring基础,这三个词条。我们需求是至少匹配两个词条,这时 operator 属性就不能满足要求了,ES 还提供了另外一个属性:minimum_should_match 用一个百分数来设定应该有多少个词条满足要求。例如查询:

“spring框架”会被分为三个词:spring、框架

示至少有两个词在文档中要匹配成功。

JavaAPI

通过 matchQuery.minimumShouldMatch 的方式来设置条件

// matchQuery全文检索 searchSourceBuilder.query(QueryBuilders.matchQuery(“description” “Spring框架”.minimumShouldMatch(“70%”)

多字段联合搜索 MultiQuery

上面的 MatchQuery 有一个短板,假如用户输入了某关键字,我们在查找的时候并不知道他输入的是 name 还是 description,这时我们用什么都不合适,而 MultiQuery 的出现解决了这个问题,他可以通过 fields 属性来设置多个域联合查找:具体用法如下

JavaAPI

searchSourceBuilder.query(QueryBuilders.multiMatchQuery(“Spring框架” “name” “description”.minimumShouldMatch(“70%”)

提升 boost

在多域联合查询的时候,可以通过 boost 来设置某个域在计算得分时候的比重,比重越高的域当他符合条件时计算的得分越高,相应的该记录也更靠前。通过在 fields 中给相应的字段用 ^权重倍数来实现

上面的代码表示给 name 字段提升十倍权重,查询到的结果:

而在 Java 中,仍然可以通过链式编程来实现

searchSourceBuilder.query(QueryBuilders.multiMatchQuery(“Spring框架” “name” “description”.field(“name” 10); // 设置 name 10倍权重

布尔查询 BoolQuery

如果我们既要对一些字段进行分词查询,同时要对另一些字段进行精确查询,就需要使用布尔查询来实现了。布尔查询对应于Lucene的BooleanQuery查询,实现将多个查询组合起来,有三个可选的参数:

must:文档必须匹配must所包括的查询条件,相当于 “AND”

should:文档应该匹配should所包括的查询条件其中的一个或多个,相当于 “OR”

must_not:文档不能匹配must_not所包括的该查询条件,相当于“NOT”

JavaAPI

// 搜索方式// 首先构造多关键字查询条件MultiMatchQueryBuilder matchQueryBuilder = QueryBuilders.multiMatchQuery“Spring框架” “name” “description”.field“name” 10// 构造精确匹配查询条件TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery“studymodel” “201002”;// 组合两个条件,组合方式为 must 全满足BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery;boolQueryBuilder.mustmatchQueryBuilderboolQueryBuilder.musttermQueryBuilder// 将查询条件封装给查询对象searchSourceBuilder.queryboolQueryBuilder

过滤器

定义过滤器查询,是在原本查询结果的基础上对数据进行筛选,因此省略了重新计算的分的步骤,效率更高。并且方便缓存。推荐尽量使用过虑器去实现查询或者过虑器和查询共同使用,过滤器在布尔查询中使用,下边是在搜索结果的基础上进行过滤:

注意:range和term一次只能对一个Field设置范围过虑。

JavaAPI

// 首先构造多关键字查询条件MultiMatchQueryBuilder matchQueryBuilder = QueryBuilders.multiMatchQuery“Spring框架” “name” “description”.field“name” 10// 添加条件到布尔查询BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery;boolQueryBuilder.mustmatchQueryBuilder// 通过布尔查询来构造过滤查询boolQueryBuilder.filterQueryBuilders.termQuery“studymodel” “201001”boolQueryBuilder.filterQueryBuilders.rangeQuery“price”.gte60.lte100;// 将查询条件封装给查询对象searchSourceBuilder.queryboolQueryBuilder

排序

我们可以在查询的结果上进行二次排序,支持对 keyword、date、float 等类型添加排序,text类型的字段不允许排序。排序使用的 JSON 格式如下:

由上面的 JSON 数据可以发现,排序所属的 API 是和 query 评级的,因此在调用 API 时也应该选择对应的 SearchSourceBuilder 对象

高亮显示

高亮显示可以将搜索结果一个或多个字突出显示,以便向用户展示匹配关键字的位置。

高亮三要素:高亮关键字、高亮前缀、高亮后缀

查询结果的数据如下:

SpringBoot操作ES进行各种高级查询(图2)

Java 代码如下,注意到上面的 JSON 数据, highlight 和 sort 和 query 依然是同级的,所以也需要用 SearchSourceBuilder 对象来设置到搜索条件中

根据查询结果的数据结构来获取高亮的数据,替换原有的数据:

private void soutDataSearchHit【 searchHits throws ParseException { SimpleDateFormat dateFormat = new SimpleDateFormat“yyyy-MM-dd HH:mm:ss”; for SearchHit hit : searchHits { // 文档的主键 String id = hit.getId; // 源文档内容 Map sourceAsMap = hit.getSourceAsMap; String name = String sourceAsMap.get“name”; // 获取高亮查询的内容。如果存在,则替换原来的name Map highlightFields = hit.getHighlightFields; if highlightFields != null { HighlightField nameField = highlightFields.get“name”; ifnameField!=null{ Text【 fragments = nameField.getFragments; StringBuffer stringBuffer = new StringBuffer; for Text str : fragments { stringBuffer.appendstr.string } name = stringBuffer.toString; } } // 由于前边设置了源文档字段过虑,这时description是取不到的 String description = String sourceAsMap.get“description”; // 学习模式 String studymodel = String sourceAsMap.get“studymodel”; // 价格 Double price = Double sourceAsMap.get“price”; // 日期 Date timestamp = dateFormat.parseString sourceAsMap.get“timestamp” System.out.printlnname System.out.printlnid System.out.printlnstudymodel System.out.println“你看不见我,看不见我~” + description System.out.printlnprice }}

本文相关词条概念解析:

查询

cháxún[question;interrogate;inquireabout]查考询问查chá考察:检查。调查。查验。查访。查阅。古同“槎”,水中浮木。询(询)xún问,征求意见:询问。询察。查询。质询。咨询。询事考言(查问考核言行是否相符)。查问;调查。清薛福成《滇缅分界大概情形疏》:“每有查询,朝电夕报。”郭鹏《刘亚生》:“我们立即向各方面展开了广泛的查询,然而,回答只有一个:没有见到这样的一位同志。”查询的意思就是查找、寻找指在某一个或几个地方找出自己所要的东西可做名词、动词[计算机]查询是从数据表中检索数据的主要方法,查询可以分为选择查询、参数查询、交叉查询和操作查询四类。

网友评论
相关文章
虽然詹姆斯的总决赛胜率低,科比62.2%排第三,总决赛胜率在这份榜单垫底的是詹姆斯

虽然詹姆斯的总决赛胜率低,科比62.2%排第三,总决赛胜率在这份榜单垫底的是詹姆斯

虽然詹姆斯的总决赛胜率低,科比62.2%排第三,总决赛胜率在这份榜单垫底的是詹姆斯[详情]

深度,深受布朗器重的哈里斯,哈里斯又能否解决二帝不兼容的难题呢

深度,深受布朗器重的哈里斯,哈里斯又能否解决二帝不兼容的难题呢

深度,深受布朗器重的哈里斯,哈里斯又能否解决二帝不兼容的难题呢[详情]

虽然联盟复赛在即,跟腱受伤的球员数不胜数,倘若复出,期待回到赛场后的杜兰特仍能重返巅峰

虽然联盟复赛在即,跟腱受伤的球员数不胜数,倘若复出,期待回到赛场后的杜兰特仍能重返巅峰

虽然联盟复赛在即,跟腱受伤的球员数不胜数,倘若复出,期待回到赛场后的杜兰特仍能重返巅峰[详情]

苦瓜也被称为食物胰岛素,甚至发酸的食物含糖也是比较高的,再穷也要舍得吃哦

苦瓜也被称为食物胰岛素,甚至发酸的食物含糖也是比较高的,再穷也要舍得吃哦

苦瓜也被称为食物胰岛素,甚至发酸的食物含糖也是比较高的,再穷也要舍得吃哦[详情]

常规赛MVP被湖人队科比获得,麦迪上榜,1.克里斯-保罗

常规赛MVP被湖人队科比获得,麦迪上榜,1.克里斯-保罗

常规赛MVP被湖人队科比获得,麦迪上榜,1.克里斯-保罗[详情]

据美国媒体称,大批示威者在白宫外聚集时,特朗普曾被带入白宫地下掩体暂短停留

据美国媒体称,大批示威者在白宫外聚集时,特朗普曾被带入白宫地下掩体暂短停留

据美国媒体称,大批示威者在白宫外聚集时,特朗普曾被带入白宫地下掩体暂短停留[详情]

我爱勒布朗的原因比篮球更重要,老船长,但是詹皇的贡献已经超出了篮球领域,乔丹可能是最棒的篮球手

我爱勒布朗的原因比篮球更重要,老船长,但是詹皇的贡献已经超出了篮球领域,乔丹可能是最棒的篮球手

我爱勒布朗的原因比篮球更重要,老船长,但是詹皇的贡献已经超出了篮球领域,乔丹可能是最棒的篮球手[详情]

不合格玩具18批次,乐高,万代等儿童玩具被点名,这不是乐高第一次上黑榜

不合格玩具18批次,乐高,万代等儿童玩具被点名,这不是乐高第一次上黑榜

不合格玩具18批次,乐高,万代等儿童玩具被点名,这不是乐高第一次上黑榜[详情]

皇马正在努力寻找新的中场核心,皇马的1亿欧元很有可能花不出去,为此齐达内开始酝酿B计划

皇马正在努力寻找新的中场核心,皇马的1亿欧元很有可能花不出去,为此齐达内开始酝酿B计划

皇马正在努力寻找新的中场核心,皇马的1亿欧元很有可能花不出去,为此齐达内开始酝酿B计划[详情]

从人人喊打到联盟第二,在执教雷霆前,一点证明他比火箭德帅强

从人人喊打到联盟第二,在执教雷霆前,一点证明他比火箭德帅强

从人人喊打到联盟第二,在执教雷霆前,一点证明他比火箭德帅强[详情]

网站地图     Copyright     2016-2018  资讯网   All rights reserved.