好玩的ES--第三篇之过滤查询,整合SpringBoot
好玩的ES--第三篇之过滤查询,整合SpringBoot
- 过滤查询
- 过滤查询
- 使用
- 类型
- term 、 terms Filter
- ranage filter
- exists filter
- ids filter
- 整合应用
- 引入依赖
- 配置客户端
- 客户端对象
- ElasticsearchOperations
- 索引文档
- 删除文档
- 查询文档
- 更新文档
- 删除所有
- 查询所有
- RestHighLevelClient
- 创建索引映射
- 索引文档
- 更新文档
- 删除文档
- 基于 id 查询文档
- 查询所有
- 综合查询
- 过滤查询
- 思路扩展
好玩的ES—第一篇之安装和基本CRUD
好玩的ES–第二篇之高级查询,索引原理和分词器
过滤查询
过滤查询
过滤查询,其实准确来说,ES中的查询操作分为2种: 查询(query)
和过滤(filter)
。查询即是之前提到的query查询
,它 (查询)默认会计算每个返回文档的得分,然后根据得分排序。而过滤(filter)
只会筛选出符合的文档,并不计算 得分,而且它可以缓存文档 。所以,单从性能考虑,过滤比查询更快。 换句话说过滤适合在大范围筛选数据,而查询则适合精确匹配数据。一般应用时, 应先使用过滤操作过滤数据, 然后使用查询匹配数据。
使用
GET /ems/emp/_search
{"query": {"bool": {"must": [{"match_all": {}} //查询条件],"filter": {....} //过滤条件}
}
注意:
- 在执行 filter 和 query 时,先执行 filter 在执行 query
- Elasticsearch会自动缓存经常使用的过滤器,以加快性能。
类型
常见过滤类型有: term 、 terms 、ranage、exists、ids等filter。
term 、 terms Filter
GET /ems/emp/_search # 使用term过滤
{"query": {"bool": {"must": [{"term": {"name": {"value": "小黑"}}}],"filter": {"term": {"content":"框架"}}}}
}
GET /dangdang/book/_search #使用terms过滤
{"query": {"bool": {"must": [{"term": {"name": {"value": "中国"}}}],"filter": {"terms": {"content":["科技","声音"]}}}}
}
ranage filter
GET /ems/emp/_search
{"query": {"bool": {"must": [{"term": {"name": {"value": "中国"}}}],"filter": {"range": {"age": {"gte": 7,"lte": 20}}}}}
}
exists filter
过滤存在指定字段,获取字段不为空的索引记录使用
GET /ems/emp/_search
{"query": {"bool": {"must": [{"term": {"name": {"value": "中国"}}}],"filter": {"exists": {"field":"aaa"}}}}
}
ids filter
过滤含有指定字段的索引记录
GET /ems/emp/_search
{"query": {"bool": {"must": [{"term": {"name": {"value": "中国"}}}],"filter": {"ids": {"values": ["1","2","3"]}}}}
}
整合应用
引入依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
配置客户端
@Data
@Configuration
public class RestClientConfig extends AbstractElasticsearchConfiguration {@Value("${es.host}")private String ES_HOST;@Override@Beanpublic RestHighLevelClient elasticsearchClient() {final ClientConfiguration clientConfiguration = ClientConfiguration.builder().connectedTo(ES_HOST).build();return RestClients.create(clientConfiguration).rest();}
}
es默认开放了两个端口进行访问,一个是9200的rest方式访问,一个是9300的tcp方式访问,这里推荐使用9200rest方式的访问
客户端对象
- ElasticsearchOperations
- RestHighLevelClient 推荐
ElasticsearchOperations
- 特点: 始终使用面向对象方式操作 ES
- 索引: 用来存放相似文档集合
- 映射: 用来决定放入文档的每个字段以什么样方式录入到 ES 中 字段类型 分词器…
- 文档: 可以被索引最小单元 json 数据格式
相关注解
@Data
@Document(indexName = "products", createIndex = true)
public class Product {@Idprivate Integer id;@Field(type = FieldType.Keyword)private String title;@Field(type = FieldType.Float)private Double price;@Field(type = FieldType.Text)private String description;
}
//1. @Document(indexName = "products", createIndex = true) 用在类上 作用:代表一个对象为一个文档-- indexName属性: 创建索引的名称-- createIndex属性: 是否创建索引
//2. @Id 用在属性上 作用:将对象id字段与ES中文档的_id对应
//3. @Field(type = FieldType.Keyword) 用在属性上 作用:用来描述属性在ES中存储类型以及分词情况-- type: 用来指定字段类型
索引文档
@Testpublic void testCreate() throws IOException {Product product = new Product();product.setId(1); //存在id指定id 不存在id自动生成idproduct.setTitle("怡宝矿泉水");product.setPrice(129.11);product.setDescription("我们喜欢喝矿泉水....");//文档不存在会创建文档,文档存在会更新文档elasticsearchOperations.save(product);}
删除文档
@Testpublic void testDelete() {Product product = new Product();product.setId(1);String delete = elasticsearchOperations.delete(product);System.out.println(delete);}
查询文档
@Testpublic void testGet() {Product product = elasticsearchOperations.get("1", Product.class);System.out.println(product);}
更新文档
@Test
public void testUpdate() {Product product = new Product();product.setId(1);product.setTitle("怡宝矿泉水");product.setPrice(129.11);product.setDescription("我们喜欢喝矿泉水,你们喜欢吗....");elasticsearchOperations.save(product);//不存在添加,存在更新
}
删除所有
@Test
public void testDeleteAll() {elasticsearchOperations.delete(Query.findAll(), Product.class);
}
查询所有
@Test
public void testFindAll() {SearchHits<Product> productSearchHits = elasticsearchOperations.search(Query.findAll(), Product.class);productSearchHits.forEach(productSearchHit -> {System.out.println("id: " + productSearchHit.getId());System.out.println("score: " + productSearchHit.getScore());Product product = productSearchHit.getContent();System.out.println("product: " + product);});
}
RestHighLevelClient
创建索引映射
@Testpublic void testCreateIndex() throws IOException {CreateIndexRequest createIndexRequest = new CreateIndexRequest("fruit");createIndexRequest.mapping("{\n" +" \"properties\": {\n" +" \"title\":{\n" +" \"type\": \"keyword\"\n" +" },\n" +" \"price\":{\n" +" \"type\": \"double\"\n" +" },\n" +" \"created_at\":{\n" +" \"type\": \"date\"\n" +" },\n" +" \"description\":{\n" +" \"type\": \"text\"\n" +" }\n" +" }\n" +" }\n" , XContentType.JSON);CreateIndexResponse createIndexResponse = restHighLevelClient.indices().create(createIndexRequest, RequestOptions.DEFAULT);System.out.println(createIndexResponse.isAcknowledged());restHighLevelClient.close();}
索引文档
@Testpublic void testIndex() throws IOException {IndexRequest indexRequest = new IndexRequest("fruit");indexRequest.source("{\n" +" \"id\" : 1,\n" +" \"title\" : \"蓝月亮\",\n" +" \"price\" : 123.23,\n" +" \"description\" : \"这个洗衣液非常不错哦!\"\n" +" }",XContentType.JSON);IndexResponse index = restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);System.out.println(index.status());}
更新文档
@Testpublic void testUpdate() throws IOException {UpdateRequest updateRequest = new UpdateRequest("fruit","qJ0R9XwBD3J1IW494-Om");updateRequest.doc("{\"title\":\"好月亮\"}",XContentType.JSON);UpdateResponse update = restHighLevelClient.update(updateRequest, RequestOptions.DEFAULT);System.out.println(update.status());}
删除文档
@Testpublic void testDelete() throws IOException {DeleteRequest deleteRequest = new DeleteRequest("fruit","1");DeleteResponse delete = restHighLevelClient.delete(deleteRequest, RequestOptions.DEFAULT);System.out.println(delete.status());}
基于 id 查询文档
@Testpublic void testGet() throws IOException {GetRequest getRequest = new GetRequest("fruit","aPbmV38BvtuRfHsTIvNo");GetResponse getResponse = restHighLevelClient.get(getRequest, RequestOptions.DEFAULT);System.out.println(getResponse.getSourceAsString());}
查询所有
public void commonExampleSearch(String indice, QueryBuilder queryBuilder) throws IOException {SearchRequest searchRequest = new SearchRequest(indice);SearchSourceBuilder sourceBuilder=new SearchSourceBuilder();sourceBuilder.query(queryBuilder);searchRequest.source(sourceBuilder);SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);System.out.println("总记录数: "+searchResponse.getHits().getTotalHits().value);System.out.println("最大得分: "+searchResponse.getHits().getMaxScore());SearchHit[] hits = searchResponse.getHits().getHits();for (SearchHit hit : hits) {System.out.println(hit.getSourceAsString());}}@Testpublic void testSearch() throws IOException {String indice="fruit";//查询所有commonExampleSearch(indice,QueryBuilders.matchAllQuery());//term查询commonExampleSearch(indice,QueryBuilders.termQuery("description","不错哦!"));//prefix查询commonExampleSearch(indice,QueryBuilders.prefixQuery("description","这个"));//通配符查询commonExampleSearch(indice,QueryBuilders.wildcardQuery("title","好*"));//ids查询--多id查询commonExampleSearch(indice,QueryBuilders.idsQuery().addIds("1","2"));//多字段查询commonExampleSearch(indice,QueryBuilders.multiMatchQuery("不错","title","description"));}
综合查询
@Testpublic void testSearch1() throws IOException {SearchRequest searchRequest = new SearchRequest("fruit");SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();sourceBuilder//分页查询.from(0)//起始位置 start=(page-1)*size.size(2)//每页显示条数,默认返回10条//指定排序字段,参数一:根据哪个字段进行排序,参数二:排序方式.sort("price", SortOrder.DESC)//返回的结果中排除或者包含哪些字段//参数1:包含的字段数组//参数2:排除字段数组.fetchSource(new String[]{"title"},new String[]{})//高亮设置.highlighter(new HighlightBuilder()//高亮显示的字段.field("description")//多字段高亮开启.requireFieldMatch(false)//自定义高亮html标签.preTags("<span style='color:red;'>").postTags("</span>"))//查询.query(QueryBuilders.termQuery("description","错"));searchRequest.source(sourceBuilder);SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);System.out.println("总条数: "+searchResponse.getHits().getTotalHits().value);SearchHit[] hits = searchResponse.getHits().getHits();for (SearchHit hit : hits) {System.out.println(hit.getSourceAsString());//显示当前查询结果中出现的高亮字段Map<String, HighlightField> highlightFields = hit.getHighlightFields();highlightFields.forEach((k,v)-> System.out.println("key: "+k + " value: "+v.fragments()[0]));}}
过滤查询
/*** query: 精确查询,查询计算文档得分,并根据文档得分进行返回* filter query: 过滤查询,用来在大量数据中筛选出本地查询相关数据,不会计算文档得分,经常使用filter query结果进行缓存* 注意: 一旦使用query和filterQuery es优先执行filter query 然后再执行 query*/@Testpublic void testFilterQuery() throws IOException {SearchRequest searchRequest=new SearchRequest("fruit");SearchSourceBuilder sourceBuilder=new SearchSourceBuilder();sourceBuilder.query(QueryBuilders.termQuery("description","不错"))//指定过滤条件.postFilter(QueryBuilders.idsQuery().addIds("1","2","3"));searchRequest.source(sourceBuilder);SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);System.out.println("符合条件的总数为: "+searchResponse.getHits().getTotalHits().value);}
思路扩展
ElasticsearchOperations面向对象的查询方式,有其优点所在,那么我们能否将其和RestHighLevelClient 进行互补呢 ?
看下面的例子:
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Data
public class Fruit implements Serializable {private String title;private Double price;private Date create_at;private String description;
}
/*** @author 大忽悠* @create 2022/3/5 11:34*/
public class AllTest extends EsApplicationTests{ObjectMapper objectMapper=new ObjectMapper();/*** 添加文档*/@Testpublic void addIndice() throws IOException {Fruit fruit = Fruit.builder().id(5).title("大忽悠").price(520.521).description("大忽悠喜欢小朋友").build();IndexRequest indexRequest=new IndexRequest("fruit");indexRequest.id(fruit.getId().toString()).source(objectMapper.writeValueAsString(fruit),XContentType.JSON);IndexResponse index = restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);System.out.println(index.status());}public void commonExampleSearch(String indice, QueryBuilder queryBuilder) throws IOException {SearchRequest searchRequest = new SearchRequest(indice);SearchSourceBuilder sourceBuilder=new SearchSourceBuilder();sourceBuilder.query(queryBuilder);searchRequest.source(sourceBuilder);SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);System.out.println("总记录数: "+searchResponse.getHits().getTotalHits().value);System.out.println("最大得分: "+searchResponse.getHits().getMaxScore());SearchHit[] hits = searchResponse.getHits().getHits();for (SearchHit hit : hits) {System.out.println("返回的结果为: "+hit.getSourceAsString());//JSON格式转换Fruit fruit = objectMapper.readValue(hit.getSourceAsString(), Fruit.class);System.out.println("得到的结果为: "+fruit);}}/*** 查询全部*/@Testpublic void searchAll() throws IOException {String indice="fruit";//查询所有commonExampleSearch(indice, QueryBuilders.matchAllQuery());}
}
注意: 两者的区别,因此我们在上传文档的时候,一定要通过objectMapper.writeValueAsString(fruit)的方式先转换为JSON串的原因
Fruit fruit = Fruit.builder().id(5).title("大忽悠").price(520.521).description("大忽悠喜欢小朋友").build();System.out.println(objectMapper.writeValueAsString(fruit));System.out.println(fruit);
好玩的ES--第三篇之过滤查询,整合SpringBoot相关推荐
- mysql怎么分组计算逾期率_转行数据分析第三篇:mysql查询入门练习题
这篇练习题是我在学sql入门的时候做的,应该算是在网上能找到的习题里最基础的一篇,非常适合新手练习,如果你接触sql不超过半个月,建议可以看一下<sql必知必会>或<mysql必知必 ...
- MySQL代做题_转行数据分析第三篇:mysql查询入门练习题
这篇练习题是我在学sql入门的时候做的,应该算是在网上能找到的习题里最基础的一篇,非常适合新手练习,如果你接触sql不超过半个月,建议可以看一下<sql必知必会>或<mysql必知必 ...
- 第三篇:Spring Boot整合Servlet
一.Springboot整合Servlet 第一种方案: 1.创建一个自定义的servlet,继承HttpServlet添加@WebServlet注解 以前ssm中的web.xml配置文件中的serv ...
- 电力负荷预测三篇综述总结
三篇综述链接: 深度学习方法在负荷预测中的应用综述(论文阅读) 光伏发电量和用电量的概率预测研究综述(1) 光伏发电量和用电量的概率预测研究综述(2) 光伏发电量和用电量的概率预测研究综述(3) 能源 ...
- ElasticSearch查询 第四篇:匹配查询(Match)
<ElasticSearch查询>目录导航: ElasticSearch查询 第一篇:搜索API ElasticSearch查询 第二篇:文档更新 ElasticSearch查询 第三篇: ...
- 第三篇 KinectV2骨骼获取原理和获取方法及源代码
第三篇 KinectV2骨骼获取原理和获取方法及源代码 首先声明一下,本系统所使用的开发环境版本是计算机系统Windows 10.Visual Studio 2013.Opencv3.0和Kinec ...
- 【数字智能三篇】之二: 一页纸说清楚“什么是推荐系统?”
按:[数字智能三篇] 目前"大数据"."推荐系统"."深度学习"是数字智能领域的热点研究方向,相关的书籍也很火热,比如"大数据&q ...
- PHP 性能分析第三篇: 性能调优实战
注意:本文是我们的 PHP 性能分析系列的第三篇,点此阅读 PHP 性能分析第一篇: XHProf & XHGui 介绍 ,或 PHP 性能分析第二篇: 深入研究 XHGui. 在本系列的 ...
- 幼儿园体育游戏电子计算机教案,幼儿园体育游戏《学会跳绳》教案三篇
[导语]让幼儿体验创造性玩绳的乐趣,引导幼儿能变换多种花样玩绳,发展幼儿动作的协调能力.增强身体机能,教幼儿抡长绳,跳大绳,锻炼孩子的跳跃能力以及孩子的节奏感.无忧考网准备了以下教案,希望对你有帮助! ...
最新文章
- 节后综合征疗愈神器,这个开源项目帮你10分钟上手AI算法开发!
- ibm服务器报错代码大全_微信认证订阅号开发者模式服务器配置自定义菜单PHP独立完整版...
- FPGA逻辑设计回顾(12)RAM以及ROM的RTL设计及其验证
- 关于sqlite数据库在使用过程中应该注意以下几点
- java同名过滤器_Gateway Redis令牌桶请求限流过滤器
- 如何写一个Python万能装饰器,既可以装饰有参数的方法,也可以装饰无参数方法,或者有无返回值都可以装饰
- 系统防止绕过程序直接数据库修改数据(金额等敏感数据)
- 常见的爬虫分析库(1)-Python3中Urllib库基本使用
- can总线报文是固定的吗_CAN总线负载率的计算方式
- Atitit it系列书籍列表 C:\Users\Administrator\Documents\it 软件系列书籍\itlist.txt C:\Users\Administrator\Docume
- 恐怖的死亡艺术,稻川淳二为自己办了场VR葬礼
- 【线性分类器】线性分类器理论知识
- python初学入门教程_初学python编程入门教程
- [软件笔试] 2014暴风影音校招技术笔试题(长春站)
- 的概念产生于计算机芯片,是指采用光导原位合成或微量点样等方法,,微阵列芯片...
- 通过自定义注解+反射的形式,使用POI实现excel的导入导出
- 全球计算机病毒损失报告,世界十大计算机病毒 CIH的危险被公认,第二经济损失26亿美元...
- 使用git push没有报错,但是远程仓库没有更新的问题
- MT8173芯片资料,MT8173处理器参数介绍
- Java基础知识系列之-抽象abstract