ElasticSearch的版本是6.3.2,其他版本可能不兼容,每一个小版本的ElasticSearch jar包可能都不兼容所以还是分清你的ElasticSearch版本吧
这里只是查询SQL关键字和ElasticSearch6.3.2API对应
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>6.3.2</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-client</artifactId>
<version>6.3.2</version>
</dependency>
<!--http-->
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>6.3.2</version>
</dependency>
上面三个缺一不可,否则会报错,上面是http方式,还有一种是java客户端但是未来会被放弃,所以就不写了,
因为使用的spring boot构建的项目,所以很多东西都帮你弄好了,只需要在配置文件中填参数就可以了
spring:
elasticsearch:
rest:
uris:
url:端口的集合
username: 账号
password: 密码
初始化客户端
@Resource
private RestHighLevelClient client;
SearchRequest searchRequest = new SearchRequest("索引名称");//设置搜索的索引
searchRequest.types("类型"); //设置搜索的类型
SearchSourceBuilder searchSourceBuilder =new SearchSourceBuilder().size(0);
size(0)代表返回数据条数为0:使用的场景,如果你分组聚合了,不想要数据,只要分组后的数据,就标为0
如果索引按时间创建的,上面填写的索引名称要加上通配符,
例如SearchRequest("index_*")
代表的是所有 index_ 开头的索引,index_2020.11.20,index_2020.11.21也会包含在内了
现在主要是原本存入MySQL中的数据存入es,所以查询把SQL语句转换成es6.3.2能识别的就行。
在es中基本上都是一个索引一个类型下进行操作,不会这个索引和另外一个完全不同的索引进行聚合等等,而7.x以后的版本都把类型给删除了,所以更加没必要担心了,你就可以想象成SQL中的单表查询
其实就是在SQL语句中select和from之间的字段如果进行函数统计,比如像这样select count(字段名) as 别名 from 表名
AggregationBuilder aggregationBuilderSum= AggregationBuilders.sum("求和后的别名").field("求和的字段");
searchSourceBuilder.aggregation(aggregationBuilderSum);
searchSourceBuilder.query(QueryBuilders.termQuery("字段",值)); //精确匹配 ,值可以是任意类型
searchSourceBuilder.query(QueryBuilders.rangeQuery("字段").gte(值)); //只可以是数值类型
searchSourceBuilder.query(QueryBuilders.rangeQuery("字段").lte(值));// 只可以是数值类型
searchSourceBuilder.query(QueryBuilders.rangeQuery("字段").gt(值));// 只可以是数值类型
searchSourceBuilder.query(QueryBuilders.rangeQuery("字段").lt(值));// 只可以是数值类型
需要注意:对于上面的这些大于小于这些如果是数值类型没问题,但是如果是日期类型就会改变,不保证符合上面的规则,关于时间类型会产生什么样的变化请看范围查询日期和数值类型区别
searchSourceBuilder.query(QueryBuilders.rangeQuery("时间字段").from("时间范围最小的时间").to("时间范围最大的时间"));
当查询到时间范围时一定要带开头时间和结尾时间,可能你会用下面的操作,
searchSourceBuilder.query(QueryBuilders.rangeQuery("时间字段").gte("时间范围最小的时间"),
但是这样可能会造成慢查询,所以需要注意
QueryBuilder queryBuilder1=QueryBuilders.termQuery("字段","值");
boolQueryBuilder.mustNot(queryBuilder1)
这里需要注意的是must_not
是需要计算评分的
QueryBuilder queryBuilder3=QueryBuilders.wildcardQuery("signature","*0-4608-433d-8d71*"); //这里的*代表是多字符匹配,还有?代表的是单字符
searchSourceBuilder.query(queryBuilder3);
其他方式的模糊匹配可以可以查看es6模糊匹配的种类区别
创建复合查询对象(将查询条件进行and or 拼接)
BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
boolQueryBuilder.must(QueryBuilder1).must(QueryBuilder2 );
这样其实就是 QueryBuilder1 and QueryBuilder2
但是不建议使用must 而是使用filter(把must换成filter就可以),因为用must时会有评分机制,造成速度会比filter慢,当然如果你使用了评分的机制就需要用must了,filter会忽略评分,造成 _score 为 0.0
上面是通用的,但是如果你只是一个字段 大于等于某个值and小于等于某个值 你可以
searchSourceBuilder.query(QueryBuilders.rangeQuery("字段").gte(值). lte(值)));
或者
searchSourceBuilder.query(QueryBuilders.rangeQuery("字段").from("大于的值").to("小于的值"));
boolQueryBuilder.should(queryBuilder1).should(queryBuilder2);
代表的就是queryBuilder1 or queryBuilder2
看下面这句语句
boolQueryBuilder.filter(queryBuilder1).should(queryBuilder2);//这里的filter看上文中的and
你可能看过上文后就认为这里的代表的含义是 queryBuilder1 or queryBuilder2
但实际上不是,实际的含义是 (queryBuilder1)or(queryBuilder1 and queryBuilder2)
,所以需要对must/filter有个清晰的思路,尤其是一个BoolQueryBuilder中同时出现must/filter和should时
举一个网上的例子:
((field1 == value1 AND field2 == value2) OR (field1 == value3))
BoolQueryBuilder first = QueryBuilders.boolQuery()
.must(QueryBuilders.termQuery(field1, value1))
.must(QueryBuilders.termQuery(field2, value2));
BoolQueryBuilder second = QueryBuilders.termQuery(field1, value3);
BoolQueryBuilder filter = new BoolQueryBuilder()
.should(first)
.should(second);
List<String> list = new ArrayList<>();
list.add("值1");
list.add("值2");
searchSourceBuilder.query(QueryBuilders.termsQuery("字段名",list));
AggregationBuilder aggregationBuilderGroup1 = AggregationBuilders.terms("分组定义的新别名").field("分组的字段").
如果多分组则再创建
AggregationBuilder aggregationBuilderGroup2= AggregationBuilders.terms("分组定义的新别名").field("分组的字段").
再连接在一起
searchSourceBuilder.aggregation(aggregationBuilderGroup1.subAggregation(aggregationBuilderGroup2));
AggregationBuilder aggregationBuilderSum= AggregationBuilders.sum("求和后的别名").field("求和的字段");
最后group和having整合一起就是下面的
searchSourceBuilder.aggregation(aggregationBuilderGroup1.subAggregation(aggregationBuilderGroup2. subAggregation(aggregationBuilderSum)));
searchSourceBuilder.sort("数值类型的值",SortOrder.DESC); // DESC降序,ASC升序
AggregationBuilder aggregationBuilderGroup = AggregationBuilders.terms("分组后的别名").field("分组字段")
.order(BucketOrder.compound(
BucketOrder.aggregation("求和的字段名", false),
BucketOrder.aggregation("第二个求和的字段名", false)));
false是降序,true是升序 首先按第一个求和值排序,第一个相同的再按第二个求和值排序
具体的例子请看:ElasticSearch里面如何分组后根据sum值排序
searchRequest.source(searchSourceBuilder);
SearchResponse searchResponse = null;
try {
searchResponse = client.search(searchRequest);
}catch (IOException e){
}
searchResponse就有你想要的数据