一、基础查询
1.查询关键字
- term:精确匹配一个字段
- match:模糊查询或者分词查询一个字段
- wildcard:使用通配符进行查询
2.查询QueryBuilders
BoolQueryBuilder queryBuilder= QueryBuilders.boolQuery();
①matchAllQuery匹配所有
queryBuilder.matchAllQuery();
②termQuery精准匹配,大小写敏感且不支持
queryBuilder.termQuery("key", value) 一次匹配一个值,完全匹配 queryBuilder.termsQuery("key", obj1, obj2..) 一次匹配多个值
③matchPhraseQuery对中文精确匹配
queryBuilder.matchPhraseQuery("key", value)
④matchQuery("key", Obj) 关键字模糊+分词匹配
queryBuilder.matchQuery(key, value);
⑤multiMatchQuery("text", "field1", "field2"..); 匹配多个字段, 关键字模糊+分词匹配
queryBuilder.multiMatchQuery(value, key1, key2, key3);
⑥组合查询
- must: AND
- mustNot: NOT
- should:: OR
queryBuilder.must(QueryBuilders.termQuery("user", "kimchy")) .mustNot(QueryBuilders.termQuery("message", "nihao")) .should(QueryBuilders.termQuery("gender", "male"));
⑦形如mysql中where条件 a=8 and (b=3 or b=4)
BoolQueryBuilder builder = QueryBuilders.boolQuery()
.must(QueryBuilders.termQuery(a,8))
.must(QueryBuilders.boolQuery()
.should(QueryBuilders.termQuery(b,3))
.should(QueryBuilders.termQuery(b,4)));
⑧查询 name字段是张三且code字段为1或2或3(或code以1/2/3开头)
这个查询比较有代表性,可以根据这一种情况的写法扩展出其他多条件范围内的查询写法:
List list = new ArrayList<>();
list.add("1");
list.add("2");
list.add("3");
第一种
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
QueryBuilder boolQueryBuilder_1= QueryBuilders.termQuery("name", "张三");
boolQueryBuilder.must(boolQueryBuilder_1);
BoolQueryBuilder boolQueryBuilder_2 = QueryBuilders.boolQuery();
list.forEach(temp ->{
boolQueryBuilder_2.should(QueryBuilders.termQuery("code", temp));
});
boolQueryBuilder.must(boolQueryBuilder_2);
第一种循环遍历list的方法可以把boolQueryBuilder_2.should里面换成前缀查询QueryBuilders.PrefixQuery("code", temp),达到前缀在一个范围内的效果
第二种
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
QueryBuilder boolQueryBuilder_1= QueryBuilders.termQuery("name", "张三");
QueryBuilder boolQueryBuilder_2= QueryBuilders.termsQuery("code", list); //注意此为termsQuery
boolQueryBuilder.must(boolQueryBuilder_1).must(boolQueryBuilder_2);
and和or同时出现时,es的写法:写两个booleanQuery,第一个:boolQuery.must,把所有要and的条件加进去,第二个boolQuery_2.should,把所有要or的条件加进去,再boolQuery.must(boolQuery_2),把boolean2加到boolean1里。
⑨QueryBuilders.wildcardQuery对分词进行模糊匹配
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
// QueryBuilders.wildcardQuery对分词进行模糊匹配
boolQueryBuilder.must(QueryBuilders.wildcardQuery("name","*胡*"));
Iterable<Student> list = dao.search(boolQueryBuilder);
for(Student s:list){
System.out.println(s);
}
3.RangeQueryBuilder范围查询,对age进行范围查询
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
boolQueryBuilder.must(QueryBuilders.wildcardQuery("name","*漫*"));
// RangeQueryBuilder范围查询,对age进行范围查询
RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("age");
rangeQueryBuilder.gte(12);
rangeQueryBuilder.lte(12);
boolQueryBuilder.must(rangeQueryBuilder);
Iterable<Student> list = dao.search(boolQueryBuilder);
for(Student s:list){
System.out.println(s);
}
二、查询
1.使用ElasticsearchRepository
①.普通的
@Autowired
private CustomerBaseRepo customerBaseRepo;
BoolQueryBuilder builder = QueryBuilders.boolQuery();
builder.must(QueryBuilders.termQuery("address", param.getAddress()));
// 方法过时
customerBaseRepo.search(builder,PageRequest.of(param.getPage() - 1, param.getSize()));
②.需要排序
@Autowired
private CustomerBaseRepo customerBaseRepo;
BoolQueryBuilder builder = QueryBuilders.boolQuery();
builder.must(QueryBuilders.termQuery("address", param.getAddress()));
FieldSortBuilder sort = SortBuilders.fieldSort("lastupdatedon").order(SortOrder.DESC);
NativeSearchQuery query = new NativeSearchQueryBuilder()
//查询封装
.withQuery(builder)
//排序封装
.withSort(sort)
.withPageable(PageRequest.of(param.getPage() - 1, param.getSize()))
.build();
// 方法过时
customerBaseRepo.search(query);
2.使用ElasticsearchRestTemplate
三、详解
1. ElasticsearchTemplate
- ElasticsearchTemplate 封装ES客户端的一些原生api模板,方便实现一些查询
elasticsearchTemplate.queryForPage #是查询一个分页列表,用的就是一个对象实例
NativeSearchQuery #是springdata中的查询条件
NativeSearchQueryBuilder #用于建造一个NativeSearchQuery查询对象
QueryBuilders #设置查询条件,是ES中的类
SortBuilders #设置排序条件
HighlightBuilder #设置高亮显示
2.QueryBuilders
- QueryBuilders是ES中的查询条件构造器
QueryBuilders.boolQuery #子方法must可多条件联查
QueryBuilders.termQuery #精确查询指定字段
QueryBuilders.matchQuery #按分词器进行模糊查询
QueryBuilders.rangeQuery #按指定字段进行区间范围查询
# 大于等于 .from .gte
# 小于等于 .to .lte
3.NativeSearchQuery
- 原生的查询条件类,用来和ES的一些原生查询方法进行搭配,实现一些比较复杂的查询,最终进行构建.build 可作为ElasticsearchTemplate. queryForPage的参数使用
//构建Search对象
NativeSearchQuery build = new NativeSearchQueryBuilder()
//条件
.withQuery(queryBuilder)
//排序
.withSort(SortBuilders.fieldSort("id").order(SortOrder.ASC))
//高亮
.withHighlightFields(name, ms)
//分页
.withPageable(PageRequest.of(pageNum - 1, pageSize))
//构建
.build();
AggregatedPage<Goods> aggregatedPage = elasticsearchTemplate.queryForPage(build, Goods.class,new Hig());
//queryForPage 参数一: NativeSearchQuery 封装的查询数据对象;参数二: es对应索引实体类;参数三: 调用高亮工具类
4.总体*查询数据至列表页面*代码,每一步均有解释
@Autowired
ElasticsearchTemplate elasticsearchTemplate;
@RequestMapping(value = "list")
public String list(@ModelAttribute(value = "vo") QueryVo vo, @RequestParam(defaultValue = "1") Integer pageNum, @RequestParam(defaultValue = "5") Integer pageSize, Model model){
//高亮显示
String pre = "<span style='color:red'>";
String post = "</span>";
//指定要高亮的字段将其加上头尾标签
HighlightBuilder.Field name = new HighlightBuilder.Field("name").preTags(pre).postTags(post);
HighlightBuilder.Field ms = new HighlightBuilder.Field("ms").preTags(pre).postTags(post);
//查询高亮结果不分片,不加此条会按分词器高亮显示(数据变少)
ms.numOfFragments(1);
//多查询条件 must 可不断添加条件
BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
if(StringUtils.isNoneBlank(vo.getName())){
//精确查询
queryBuilder.must(QueryBuilders.termQuery("name.keyword",vo.getName()));
}
if(StringUtils.isNoneBlank(vo.getMs())){
//模糊查询
queryBuilder.must(QueryBuilders.matchQuery("ms",vo.getMs()));
}
//根据指定字段区间查询 from(gte) 大于等于 to(lte) 小于等于
RangeQueryBuilder rangeQuery = QueryBuilders.rangeQuery("price");
if(vo.getStartpice() != null){
rangeQuery.from(vo.getStartpice());
}
if(vo.getEndpice() != null){
rangeQuery.to(vo.getEndpice());
}
queryBuilder.must(rangeQuery);
//构建Search对象
NativeSearchQuery build = new NativeSearchQueryBuilder()
//条件
.withQuery(queryBuilder)
//排序
.withSort(SortBuilders.fieldSort("id").order(SortOrder.ASC))
//高亮
.withHighlightFields(name, ms)
//分页
.withPageable(PageRequest.of(pageNum - 1, pageSize))
//构建
.build();
AggregatedPage<Goods> aggregatedPage = elasticsearchTemplate.queryForPage(build, Goods.class,new Hig());
//封装分页数据至list集合中
Page<Goods> page = new Page<>(pageNum, pageSize);
//填充分页总条数
page.setTotal(aggregatedPage.getTotalElements());
//封装至pageinfo内,实现列表
PageInfo<Goods> pg = new PageInfo<>(page);
//将es查询到当前页的数据 封装至pg中
pg.setList(aggregatedPage.getContent());
//传入前端,实现列表页面
model.addAttribute("pg",pg);
return "list";
}
认真看的伙伴可以看出上方我引入了高亮工具类,下面对高亮工具类进行详解(亮点)
//es高亮工具类
public class Hig implements SearchResultMapper {
/*
searchResponse 封装高亮查询结果集
clazz 要封装的es索引对应实体类对象
pageable
*/
@Override
public <T> AggregatedPage<T> mapResults(SearchResponse searchResponse, Class<T> clazz, Pageable pageable) {
//获取es搜索数据集合对象
SearchHits hits = searchResponse.getHits();
//获取高亮搜索后数据的总条数
long totalHits = hits.getTotalHits();
//搭建存储数据集合对象
ArrayList<T> list = new ArrayList<>();
//判断高亮结果有数据
if(hits.getHits().length > 0){
//遍历数据集合
for (SearchHit searchHit : hits) {
//获取结果集中所有要高亮字段
final Map<String, HighlightField> highlightFields = searchHit.getHighlightFields();
//把json串转为目标对象
T t = JSON.parseObject(searchHit.getSourceAsString(), clazz);
//获取目标对象的所有属性
Field[] fields = clazz.getDeclaredFields();
//遍历属性
for (Field field : fields) {
//打破私有封装
field.setAccessible(true);
如果高亮的字段和要封装的对象的名字一致则值要重新封装
if(highlightFields.containsKey(field.getName())){
try {
//将查询到的数据进行高亮替换
field.set(t,highlightFields.get(field.getName()).fragments()[0].toString());
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
//存入数据集合中
list.add(t);
}
}
//返回数据集合,排序对象,集高亮总条数
return new AggregatedPageImpl<>(list,pageable,totalHits);
}
}