前言
本篇文字我记录了ES相关的部分查询方法。
提示:以下是本篇文章正文内容,下面案例可供参考
一、分词条件查询(and/or)
代码如下(示例):
controller
/**
* 功能描述: 分词条件查询(and/or)
*
* @param indexName 索引名
* @param queryObjectList
* @return : List<Map<String, String>>
*/
@PostMapping("/participle")
@ApiOperation(value = "分词条件查询", notes = "根据索引名、域名、查询关键字分词查询数据")
public BasePageResponse participleQuery(@RequestParam("indexName") String indexName,
@RequestBody @Validated List<QueryObject> queryObjectList,
@RequestParam(value = "page", required = false, defaultValue = "1") Integer page,
@RequestParam(value = "pageSize", required = false, defaultValue = "10") Integer pageSize
) throws IOException, SelectException {
return pageOk(esqService.participleQuery(indexName, queryObjectList, page, pageSize));
}
service
public Page participleQuery(String indexName, List<QueryObject> queryObjectList,Integer page,Integer pageSize) throws IOException, SelectException {
SearchRequest searchRequest = new SearchRequest(indexName);
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
List<QueryBuilder> should = boolQueryBuilder.should();
HighlightBuilder highlightBuilder = new HighlightBuilder().preTags(Constant.PRESPAN).postTags(Constant.POSTSPAN);
List<HighlightBuilder.Field> fields = highlightBuilder.fields();
for (QueryObject queryObject : queryObjectList) {
MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery(queryObject.getField(), queryObject.getData()).operator(queryObject.getChoice() ? Operator.OR : Operator.AND);
should.add(matchQueryBuilder);
fields.add(new HighlightBuilder.Field(queryObject.getField()));
sourceBuilder.highlighter(highlightBuilder);
searchRequest.source(sourceBuilder);
}
sourceBuilder.query(boolQueryBuilder);
sourceBuilder.highlighter(highlightBuilder);
searchRequest.source(sourceBuilder);
sourceBuilder.from(page-1);//从第几条开始(相当于ES 里大括号下的page)
sourceBuilder.size(pageSize);//查询多少条(相当于ES 里大括号下的pageSize)
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
SearchHits hits = searchResponse.getHits();
SearchHit[] hitsHits = hits.getHits();
List list = new ArrayList();
for (SearchHit hitsHit : hitsHits) {
String sourceAsString = hitsHit.getSourceAsString();
Map<String, String> map = JSONObject.fromObject(sourceAsString);
// 获取高亮结果,替换goods中的title
Map<String, HighlightField> highlightFields = hitsHit.getHighlightFields();
for (QueryObject queryObject : queryObjectList) {
HighlightField highlightField = highlightFields.get(queryObject.getField());
if (highlightField == null) {
continue;
}
Text[] fragments = highlightField.fragments();
String fieldValue = fragments[0].toString();
map.put(queryObject.getField(), fieldValue);
list.add(JSONObject.fromObject(map).toString());
}
}
Page pages = new Page(page, pageSize);
pages.setTotal(hits.getTotalHits().value);
pages.setRecords(list);
return pages;
}
二、通配符模糊查询 * or ?
代码如下(示例):
controller
/**
* 功能描述: 通配符模糊查询 * or ?
*
* @param indexName 索引名
* @return : java.util.List<java.util.Map<java.lang.String,java.lang.String>>
*/
@PostMapping("/wildcard")
@ApiOperation(value = "模糊通配符查询", notes = "根据*/?查询数据")
public BasePageResponse wildcardQuery(@RequestParam("indexName") String indexName, @Validated @RequestBody List<QueryObject> queryObjectList,
@RequestParam(value = "page", required = false, defaultValue = "1") Integer page,
@RequestParam(value = "pageSize", required = false, defaultValue = "10") Integer pageSize)
throws SelectException, IOException {
if (queryObjectList == null || queryObjectList.isEmpty()) {
throw new SelectException(ResponseEnum.DATA_NULL);
}
return pageOk(esqService.wildcardQuery(indexName, queryObjectList, page, pageSize));
}
service
public Page wildcardQuery(String indexName, List<QueryObject> queryObjectList,Integer page,Integer pageSize) throws SelectException, IOException {
SearchRequest searchRequest = new SearchRequest(indexName);
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
List<QueryBuilder> should = boolQueryBuilder.should();
HighlightBuilder highlightBuilder = new HighlightBuilder().preTags(Constant.PRESPAN).postTags(Constant.POSTSPAN);
List<HighlightBuilder.Field> fields = highlightBuilder.fields();
for (QueryObject queryObject : queryObjectList) {
WildcardQueryBuilder wildcardQueryBuilder = QueryBuilders.wildcardQuery(queryObject.getField(), queryObject.getData() + (queryObject.getChoice() ? "*" : "?"));
should.add(wildcardQueryBuilder);
fields.add(new HighlightBuilder.Field(queryObject.getField()));
sourceBuilder.highlighter(highlightBuilder);
searchRequest.source(sourceBuilder);
}
sourceBuilder.query(boolQueryBuilder);
sourceBuilder.highlighter(highlightBuilder);
searchRequest.source(sourceBuilder);
sourceBuilder.from(page-1); //从第几条开始(相当于ES 里大括号下的page)
sourceBuilder.size(pageSize); //查询多少条(相当于ES 里大括号下的pageSize)
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
SearchHits hits = searchResponse.getHits();
SearchHit[] hitsHits = hits.getHits();
List list = new ArrayList();
for (SearchHit hitsHit : hitsHits) {
String sourceAsString = hitsHit.getSourceAsString();
Map<String, String> map = JSONObject.fromObject(sourceAsString);
Map<String, HighlightField> highlightFields = hitsHit.getHighlightFields();
for (QueryObject queryObject : queryObjectList) {
HighlightField highlightField = highlightFields.get(queryObject.getField());
if (highlightField == null) {
continue;
}
Text[] fragments = highlightField.fragments();
String fieldValue = fragments[0].toString();
map.put(queryObject.getField(), fieldValue);
list.add(JSONObject.fromObject(map).toString());
}
}
Page pages = new Page(page,pageSize);
pages.setTotal(hits.getTotalHits().value);
pages.setRecords(list);
return pages;
}
三、错误纠正
代码如下(示例):
controller
/**
* 功能描述: correct 纠错
*
* @param indexName 索引名
* @param field 字段
* @param keyword 查询关键字
* @return : cn.chinaunicom.sdsi.framework.response.BaseResponse<java.util.List<java.lang.Object>>
*/
@ApiOperation(value = "错误纠正")
@PostMapping("/correct")
public BaseResponse correct(@RequestParam("indexName") String indexName, @RequestParam("field") String field, @RequestParam("keyword") String keyword) {
List<Object> list = new ArrayList<>();
if (StringUtils.isNotBlank(indexName) && StringUtils.isNotBlank(field) && StringUtils.isNotBlank(keyword)) {
list = esqService.correct(indexName, field, keyword);
}
return ok(list);
}
service
public List<Object> correct(String indexName, String field, String keyword) {
List<Object> list = new ArrayList<>();
SearchRequest searchRequest = new SearchRequest(indexName);
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
SearchResponse searchResponse = null;
try {
SuggestionBuilder termSuggestionBuilder = SuggestBuilders.termSuggestion(field).text(keyword);
SuggestBuilder suggestBuilder = new SuggestBuilder();
suggestBuilder.addSuggestion("suggest_user", termSuggestionBuilder);
sourceBuilder.suggest(suggestBuilder);
searchRequest.source(sourceBuilder);
searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
} catch (IOException e) {
log.error("纠错查询失败!{}",e);
e.printStackTrace();
}
Suggest suggest = searchResponse.getSuggest();
if(RestStatus.OK.equals(searchResponse.status())) {
TermSuggestion suggestion = suggest.getSuggestion("suggest_user");
for (TermSuggestion.Entry options : suggestion) {
for (TermSuggestion.Entry.Option option : options) {
String suggestText = String.valueOf(option.getText());
list.add(suggestText);
}
}
}
return list;
}
四、模糊查询
代码如下(示例):
controller
/**
* 功能描述: 模糊查询
*
* @param indexName 索引名
* @param field 域
* @param data 查询数据
* fuzzy才是实现真正的模糊查询,我们输入的字符可以是个大概,他可以根据我们输入的文字大概进行匹配查询
* @return : java.util.List<java.lang.String>
*/
@ApiOperation(value = "模糊查询", notes = "根据索引名、域名、关键字模糊查询数据")
@PostMapping("/fuzzy")
public BasePageResponse fuzzyQuery(@RequestParam("indexName") String indexName,
@RequestParam("field") String field,
@RequestParam("data") String data,
@RequestParam(value = "page", required = false, defaultValue = "1") Integer page,
@RequestParam(value = "pageSize", required = false, defaultValue = "10") Integer pageSize) throws Exception {
if (!StringUtils.isEmpty(indexName) && !StringUtils.isEmpty(field) && !StringUtils.isEmpty(data)) {
return pageOk(esqService.fuzzyQuery(indexName, field, data, page, pageSize));
} else {
log.error(String.valueOf(ResponseEnum.DATA_NULL));
throw new Exception(String.valueOf(ResponseEnum.DATA_NULL));
}
}
service
public Page fuzzyQuery(String indexName, String field, String data, Integer page,Integer pageSize) {
SearchResponse searchResponse = null;
List<Object> list = new ArrayList<>();
SearchRequest searchRequest = new SearchRequest(indexName);
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
try {
QueryBuilder queryBuilder = QueryBuilders.fuzzyQuery(field, data).fuzziness(Fuzziness.ONE);
sourceBuilder.query(queryBuilder);
HighlightBuilder highlightBuilder = new HighlightBuilder()
.field(field)
.preTags(Constant.PRESPAN)
.postTags(Constant.POSTSPAN);
sourceBuilder.highlighter(highlightBuilder);
sourceBuilder.from(page-1);
sourceBuilder.size(pageSize);
searchRequest.source(sourceBuilder);
searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
SearchHits hits = searchResponse.getHits();
SearchHit[] hitsHits = hits.getHits();
for (SearchHit hitsHit : hitsHits) {
String sourceAsString = hitsHit.getSourceAsString();
Map<String, String> map = JSONObject.fromObject(sourceAsString);
Map<String, HighlightField> highlightFields = hitsHit.getHighlightFields();
HighlightField highlightAddress = highlightFields.get(field);
if (highlightFields.containsKey(field)) {
Text[] titleTexts = highlightAddress.fragments();
StringBuffer address = new StringBuffer();
for (Text text : titleTexts) {
address.append(text);
}
map.put(field, String.valueOf(address));
String s = String.valueOf(JSONObject.fromObject(map));
list.add(s);
}
}
} catch (IOException e) {
log.error("fuzzyQuery方法调用失败!-->{}",e);
e.printStackTrace();
}
SearchHits hits = searchResponse.getHits();
Page pages = new Page(page,pageSize);
pages.setTotal(hits.getTotalHits().value);
pages.setRecords(list);
return pages;
}
五、精确查询
这里的精确查询是多字段的精确查询,支持范围查询(时间范围,数值范围),还支持部分字段的模糊查询,是一个综合查询。
代码如下(示例):
controller
/**
* 功能描述: 精确查询
*
* @param indexName 索引名
* @param boolQueryObjectList 字段+关键字
* @param highOrNot 是否高亮
* @param pageOrNot 是否分页
* @return : java.util.List<java.lang.String>
*/
@ApiOperation(value = "精确查询", notes = "根据索引名、域名、查询关键字精确查询数据")
@PostMapping("/term")
public BasePageResponse termQuery(@RequestParam("indexName") String indexName,
@RequestParam("highOrNot") boolean highOrNot,
@RequestParam("pageOrNot") boolean pageOrNot,
@RequestBody @Validated List<BoolQueryObject> boolQueryObjectList,
@RequestParam(value = "page", required = false, defaultValue = "1") Integer page,
@RequestParam(value = "pageSize", required = false, defaultValue = "10") Integer pageSize) throws Exception {
if (!StringUtils.isEmpty(indexName) && boolQueryObjectList.size()>0) {
return pageOk(esqService.termQuery(indexName, highOrNot,pageOrNot, boolQueryObjectList, page, pageSize));
} else {
log.error(String.valueOf(ResponseEnum.DATA_NULL));
throw new Exception(String.valueOf(ResponseEnum.DATA_NULL));
}
}
service
public Page termQuery(String indexName,boolean highOrNot,boolean pageOrNot,List<BoolQueryObject> boolQueryObjectList,Integer page,Integer pageSize) {
SearchResponse searchResponse = null;
List<Object> list = new ArrayList<>();
SearchRequest searchRequest = new SearchRequest(indexName);
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
try {
HighlightBuilder highlightBuilder = new HighlightBuilder().preTags(Constant.PRESPAN).postTags(Constant.POSTSPAN);
List<HighlightBuilder.Field> fields = highlightBuilder.fields();
List<BoolQueryObject> normalList = null;
if (boolQueryObjectList.size()>0) {
List<BoolQueryObject> fuzzyList = boolQueryObjectList.stream()
.filter(b -> b.getFiledType().equals(Constant.FUZZY))
.collect(Collectors.toList());
if (fuzzyList.size()>0){
for (BoolQueryObject queryObject : fuzzyList){
FuzzyQueryBuilder fuzzyQueryBuilder = QueryBuilders.fuzzyQuery(queryObject.getField(),queryObject.getValues()[0]);
boolQueryBuilder.must(fuzzyQueryBuilder);
if (highOrNot) {
fields.add(new HighlightBuilder.Field(queryObject.getField()));
sourceBuilder.highlighter(highlightBuilder);
}
searchRequest.source(sourceBuilder);
}
}
normalList = boolQueryObjectList.stream()
.filter(b -> b.getFiledType().equals(Constant.NORMAL))
.collect(Collectors.toList());
if (normalList.size()>0) {
for (BoolQueryObject queryObject : normalList) {
TermsQueryBuilder matchQueryBuilder = QueryBuilders.termsQuery(queryObject.getField(), queryObject.getValues());
boolQueryBuilder.must(matchQueryBuilder);
if (highOrNot) {
fields.add(new HighlightBuilder.Field(queryObject.getField()));
sourceBuilder.highlighter(highlightBuilder);
}
searchRequest.source(sourceBuilder);
}
}
List<BoolQueryObject> datelList = boolQueryObjectList.stream()
.filter(b -> b.getFiledType().equals(Constant.DATE))
.collect(Collectors.toList());
if(datelList.size()>0) {
RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery(datelList.get(0).getField())
.gte(String.valueOf(datelList.get(0).getValues()[0]))
.lte(String.valueOf(datelList.get(0).getValues()[1]))
.format("yyyy-MM-dd HH:mm:ss");
boolQueryBuilder.must(rangeQueryBuilder);
}
List<BoolQueryObject> beginDatelList = boolQueryObjectList.stream()
.filter(b -> b.getFiledType().equals(Constant.BEGIN_DATE))
.collect(Collectors.toList());
if(beginDatelList.size()>0) {
RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery(beginDatelList.get(0).getField())
.gte(String.valueOf(beginDatelList.get(0).getValues()[0]))
.format("yyyy-MM-dd HH:mm:ss");
boolQueryBuilder.must(rangeQueryBuilder);
}
List<BoolQueryObject> endDatelList = boolQueryObjectList.stream()
.filter(b -> b.getFiledType().equals(Constant.END_DATE))
.collect(Collectors.toList());
if(endDatelList.size()>0) {
RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery(endDatelList.get(0).getField())
.lte(String.valueOf(endDatelList.get(0).getValues()[0]))
.format("yyyy-MM-dd HH:mm:ss");
boolQueryBuilder.must(rangeQueryBuilder);
}
List<BoolQueryObject> pricelList = boolQueryObjectList.stream()
.filter(b -> b.getFiledType().equals(Constant.ESPRICE))
.collect(Collectors.toList());
if (pricelList.size()>0){
BigDecimal pageData = new BigDecimal(String.valueOf(pricelList.get(0).getValues()[0])).setScale(5);
QueryBuilder reangeBuilder;
if (pricelList.get(0).getValues().length == 1 || StringUtils.isBlank(pricelList.get(0).getValues()[1])){
reangeBuilder = QueryBuilders.rangeQuery(pricelList.get(0).getField()).gte(pageData);
}else {
BigDecimal toData = new BigDecimal(String.valueOf(pricelList.get(0).getValues()[1])).setScale(5);
reangeBuilder = QueryBuilders.rangeQuery(pricelList.get(0).getField()).gte(pageData).lte(toData);
}
boolQueryBuilder.must(reangeBuilder);
}
}
sourceBuilder.query(boolQueryBuilder);
sourceBuilder.from(page - 1);
if (!pageOrNot){
pageSize = 10000;
}
sourceBuilder.size(pageSize);
searchRequest.source(sourceBuilder);
searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
SearchHits hits = searchResponse.getHits();
SearchHit[] hitsHits = hits.getHits();
for (SearchHit hitsHit : hitsHits) {
String sourceAsString = hitsHit.getSourceAsString();
if (highOrNot) {
Map<String, String> map = JSONObject.fromObject(sourceAsString);
Map<String, HighlightField> highlightFields = hitsHit.getHighlightFields();
if (normalList.size() > 0) {
for (BoolQueryObject queryObject : boolQueryObjectList) {
HighlightField highlightField = highlightFields.get(queryObject.getField());
if (highlightField == null) {
continue;
}
Text[] fragments = highlightField.fragments();
String fieldValue = fragments[0].toString();
map.put(queryObject.getField(), fieldValue);
list.add(JSONObject.fromObject(map).toString());
}
}else {
list.add(sourceAsString);
}
}else {
list.add(sourceAsString);
}
}
} catch (IOException e) {
log.error("termQuery方法调用失败!-->{}",e);
e.printStackTrace();
}
Page pages = new Page(page,pageSize);
pages.setTotal(searchResponse.getHits().getTotalHits().value);
pages.setRecords(list);
return pages;
}
六、范围查询
代码如下(示例):
controller
/**
* 功能描述: reange 范围查询
*
* @param indexName 索引名
* @param field 域名
* @param pageData toData 查询关键字
* @return : java.util.List<java.lang.String>
*/
@ApiOperation(value = "范围查询", notes = "根据索引名、域名、范围查询数据")
@PostMapping("/reange")
public BasePageResponse reangeQuery(@RequestParam("indexName") String indexName,
@RequestParam("field") String field,
@RequestParam("type") String type,
@RequestParam("pageData") Object pageData,
@RequestParam("toData") Object toData,
@RequestParam(value = "page", required = false, defaultValue = "1") Integer page,
@RequestParam(value = "pageSize", required = false, defaultValue = "10") Integer pageSize) throws Exception {
if (!StringUtils.isEmpty(indexName) && !StringUtils.isEmpty(field)
&& !StringUtils.isEmpty(String.valueOf(pageData)) && !StringUtils.isEmpty(String.valueOf(toData))) {
return pageOk(esqService.reangeQuery(indexName, field, type, pageData, toData, page, pageSize));
} else {
log.error(String.valueOf(ResponseEnum.DATA_NULL));
throw new Exception(String.valueOf(ResponseEnum.DATA_NULL));
}
}
service
public Page reangeQuery(String indexName, String field, String type, Object pageData, Object toData,Integer page,Integer pageSize) {
SearchResponse searchResponse = null;
List<Object> list = new ArrayList<>();
SearchRequest searchRequest = new SearchRequest(indexName);
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
try{
QueryBuilder queryBuilder = null;
if (type.equals(Constant.ESPRICE)) {
BigDecimal bigdata1 = new BigDecimal(String.valueOf(pageData)).setScale(5);
BigDecimal bigdata2 = new BigDecimal(String.valueOf(toData)).setScale(5);
queryBuilder = QueryBuilders.rangeQuery(field).gte(bigdata1).lte(bigdata2);
}else if (type.equals(Constant.DATE)){
queryBuilder = QueryBuilders.rangeQuery(field).from(String.valueOf(pageData)).to(String.valueOf(toData)).format("yyyy-MM-dd");
}
sourceBuilder.query(queryBuilder);
sourceBuilder.from(page-1);
sourceBuilder.size(pageSize);
searchRequest.source(sourceBuilder);
searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
SearchHits hits = searchResponse.getHits();
SearchHit[] hitsHits = hits.getHits();
for (SearchHit hitsHit : hitsHits) {
String sourceAsString = hitsHit.getSourceAsString();
list.add(sourceAsString);
}
} catch (IOException e) {
log.error("reangeQuery方法调用失败!-->{}",e);
e.printStackTrace();
}
SearchHits hits = searchResponse.getHits();
Page pages = new Page(page,pageSize);
pages.setTotal(hits.getTotalHits().value);
pages.setRecords(list);
return pages;
}
七、suggestion搜索建议
代码如下(示例):
controller
/**
* 功能描述: suggestion搜索建议
*
* @param indexName 索引名
* @param field 域名
* @param data 查询关键字
* @return : java.util.List<java.lang.String>
*/
@ApiOperation(value = "搜索建议", notes = "根据索引名、域名、查询关键字查询搜索建议")
@PostMapping("suggestion")
public BaseResponse suggestionQuery(@RequestParam(value = "indexName") String indexName,
@RequestParam(value = "field") String field,
@RequestParam(value = "data") String data) throws Exception {
List<String> suggestionList = new ArrayList<>();
if (NotEmptyUtiles.Judgment(indexName,field,data)) {
suggestionList = esqService.suggestionQuery(indexName, field, data);
return ok(suggestionList);
} else {
log.error(String.valueOf(ResponseEnum.DATA_NULL));
throw new Exception(String.valueOf(ResponseEnum.DATA_NULL));
}
}
service
public List<String> suggestionQuery(String indexName, String field, String data) {
List<String> suggestionList = new ArrayList<>();
SearchRequest searchRequest = new SearchRequest(indexName);
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.size(0);
try{
SuggestionBuilder termSuggestionBuilder =SuggestBuilders
.completionSuggestion(field).prefix(data)
.skipDuplicates(true)
.size(10);
SuggestBuilder suggestBuilder = new SuggestBuilder();
suggestBuilder.addSuggestion(Constant.SUGGEST, termSuggestionBuilder);
sourceBuilder.suggest(suggestBuilder);
searchRequest.source(sourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest,RequestOptions.DEFAULT);
if(RestStatus.OK.equals(searchResponse.status())) {
Suggest suggest = searchResponse.getSuggest();
CompletionSuggestion termSuggestion = suggest.getSuggestion(Constant.SUGGEST);
for (CompletionSuggestion.Entry entry : termSuggestion.getEntries()) {
for (CompletionSuggestion.Entry.Option option : entry) {
String suggestText = option.getText().string();
log.info(" suggest option : -->{}",suggestText);
suggestionList.add(suggestText);
}
}
}
} catch (IOException e) {
log.error("suggestionQuery方法调用失败!-->{}",e);
e.printStackTrace();
}
return suggestionList;
}
总结
综上,就是项目中用到的部分查询方法,大家可以借鉴下哈,下一篇我将把最重要的聚合查询和bool查询,以及极值(最大值最小值)聚合查询分享给大家。。