Service public class ClassificationOfDiseasesServiceImpl { private static final Logger log = LoggerFactory.getLogger(ClassificationOfDiseasesServiceImpl.class); private final RestHighLevelClient client; public ClassificationOfDiseasesServiceImpl(RestHighLevelClient client) { this.client = client; } @Autowired private ClassificationClient classificationClient; //索引名称 public static final String CLASSIFICATION_OF_DISEASES = "classificationofdiseases"; /** * 单个新增 * * @param id * @return */ public BaseResponse insert(String id) { BaseRequest baseRequest = new BaseRequest(); if (StringUtils.isEmpty(id)) { return BaseResponse.error(); } BaseResponse baresponse = BaseResponse.success(); baseRequest.setRequest(id); baseRequest.setHeaders(new Headers()); BaseResponse<ClassificationOfDiseases> clientInfo = classificationClient.getInfo(baseRequest); IndexRequest request = new IndexRequest(CLASSIFICATION_OF_DISEASES); Map<String, Object> jsonMap = null; if (clientInfo != null && clientInfo.getResponse() != null) { jsonMap = JSONObject.parseObject(JSONObject.toJSONString(clientInfo.getResponse()), Map.class); } else { return BaseResponse.error(); } // request.source(jsonMap); IndexResponse response = null; try { response = client.index(request, EsConfig.COMMON_OPTIONS); if (response.getResult().name().equalsIgnoreCase("created")) { return baresponse; } else { return BaseResponse.error(); } } catch (IOException e) { e.printStackTrace(); } return BaseResponse.error(); } /** * 批量新增 * * @param barequest * @return */ public BaseResponse batchInsert(BaseRequest barequest) { BaseResponse response = BaseResponse.success(); BaseRequest baseRequest = new BaseRequest(); baseRequest.setRequest("123"); baseRequest.setHeaders(new Headers()); //查询数据 List<ClassificationOfDiseases> list = classificationClient.saveClassificationOfDiseases(baseRequest); if (list.size() <= 0) { return BaseResponse.error(); } //批量从插入数据 BulkRequest request = new BulkRequest(); //设置分片超时时间 TimeValue.timeValueSeconds(1) //request.timeout("2m"); //设置刷新策略,若未设置最常见的情况就是执行es中数据更新或插入, // 同步去查询时数据发现没有更新 WriteRequest.RefreshPolicy.WAIT_UNTIL //request.setRefreshPolicy("wait_for"); //request.waitForActiveShards(3); //通过设置poType为“update”or“create”设置更新或者修改 DocWriteRequest.OpType.CREATE //request.opType("create"); for (ClassificationOfDiseases dis : list) { Map<String, Object> item = JSONObject.parseObject(JSONObject.toJSONString(dis), Map.class); request.add(new IndexRequest(CLASSIFICATION_OF_DISEASES). source(item)); } try { BulkResponse bulk = client.bulk(request, EsConfig.COMMON_OPTIONS); if (bulk.status().getStatus() == 200) { return response; } } catch (IOException e) { e.printStackTrace(); } return BaseResponse.error(); } /** * 创建索引 * @return * @throws IOException */ public BaseResponse createIndex() throws IOException { BaseResponse response = BaseResponse.success(); try{ CreateIndexRequest request = new CreateIndexRequest(CLASSIFICATION_OF_DISEASES); Settings.Builder builder = Settings.builder(); // 分片数 builder.put("index.number_of_shards", 3); // 副本数 builder.put("index.number_of_replicas", 2); builder.put("analysis.analyzer.default.tokenizer", "ik_max_word"); // 默认分词器 request.settings(builder); CreateIndexResponse createIndexResponse = client.indices().create(request, EsConfig.COMMON_OPTIONS); if (createIndexResponse.isShardsAcknowledged()){ return response; } }catch (Exception e){ response.setCode("400"); response.setMessage(e.getMessage()); return response; } return BaseResponse.error(); } /** * 修改 * * @param reque * @return */ public BaseResponse update(String id, BaseRequest<ClassificationOfDiseases> reque) { ClassificationOfDiseases requ = reque.getRequest(); BaseResponse response = BaseResponse.success(); Map<String, Object> map = null; map = JSONObject.parseObject(JSONObject.toJSONString(requ), Map.class); UpdateRequest request = new UpdateRequest(CLASSIFICATION_OF_DISEASES, map.get("id").toString()).doc(map); //目标doc有就更新、没有就新增 request.docAsUpsert(false); try { UpdateResponse update = client.update(request, EsConfig.COMMON_OPTIONS); if (update.status().getStatus() == 200) { return response; } else { return BaseResponse.error(); } } catch (IOException e) { e.printStackTrace(); } return null; } /** * 查询 疾病 * @param barequest * @return */ public BaseResponse queryIllness(BaseRequest<ClassificationOfDiseases> barequest) { BaseResponse response = BaseResponse.success(); // if (null == barequest || barequest.getRequest() == null) { response.setCode("201"); response.setMessage("请求数据为空!"); return response; } if (StringUtils.isEmpty( barequest.getRequest().getDiseasesName())){ response.setCode("201"); response.setMessage("请求疾病名称数据为空!"); return response; } SearchRequest request = new SearchRequest(CLASSIFICATION_OF_DISEASES); ClassificationOfDiseases ofDiseases = barequest.getRequest(); //疾病名称 String diseasesName = ofDiseases.getDiseasesName(); BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery(); //或者 //boolQueryBuilder.should(QueryBuilders.termQuery("diseasName",diseasName)); boolQueryBuilder.filter(QueryBuilders.termQuery("diseasesName.keyword", diseasesName)); SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); //分页 searchSourceBuilder.from(0).size(10); searchSourceBuilder.query(boolQueryBuilder); // request.searchType(SearchType.DEFAULT).source(searchSourceBuilder); List<Map<String, Object>> list = new ArrayList<>(); try { SearchResponse searchResponse = client.search(request, EsConfig.COMMON_OPTIONS); for (SearchHit s : searchResponse.getHits().getHits()) { // Map<String, Object> sourceAsMap = s.getSourceAsMap(); list.add(sourceAsMap); } } catch (IOException e) { e.printStackTrace(); } if (list.size() <= 0) { response.setCode("201"); response.setMessage("查询数据为空!"); return response; } response.setResponse(list); return response; } /** * 查询 * @param barequest * @return */ public BaseResponse queryDiseases(BaseRequest<ClassificationOfDiseases> barequest) { BaseResponse response = BaseResponse.success(); // if (null == barequest || barequest.getRequest() == null) { response.setCode("201"); response.setMessage("请求数据为空!"); return response; } if (StringUtils.isEmpty( barequest.getRequest().getDiseasesName())){ response.setCode("201"); response.setMessage("请求数据为空!"); return response; } SearchRequest request = new SearchRequest(CLASSIFICATION_OF_DISEASES); ClassificationOfDiseases ofDiseases = barequest.getRequest(); //疾病名称 String diseasesName = ofDiseases.getDiseasesName(); BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery(); boolQueryBuilder.filter(QueryBuilders.termQuery("diseasesName.keyword", diseasesName)); SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); //分页 searchSourceBuilder.from(0).size(100); searchSourceBuilder.query(boolQueryBuilder); // request.searchType(SearchType.DEFAULT).source(searchSourceBuilder); List<Map<String, Object>> list = new ArrayList<>(); try { SearchResponse searchResponse = client.search(request, EsConfig.COMMON_OPTIONS); for (SearchHit s : searchResponse.getHits().getHits()) { // Map<String, Object> sourceAsMap = s.getSourceAsMap(); list.add(sourceAsMap); } } catch (IOException e) { e.printStackTrace(); } if (list.size() <= 0) { response.setCode("201"); response.setMessage("查询数据为空!"); return response; } response.setResponse(list); return response; } public BaseResponse queryId(BaseRequest<Map<String ,Object>> barequest) { BaseResponse response = BaseResponse.success(); // if (null == barequest || barequest.getRequest().isEmpty()) { response.setCode("201"); response.setMessage("请求数据为空!"); return response; } SearchRequest request = new SearchRequest(CLASSIFICATION_OF_DISEASES); Map<String, Object> map = barequest.getRequest(); String id = (String)map.get("id"); //疾病名称 BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery(); boolQueryBuilder.filter(QueryBuilders.termQuery("id.keyword", id)); SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); //分页 searchSourceBuilder.from(0).size(100); searchSourceBuilder.query(boolQueryBuilder); // request.searchType(SearchType.DEFAULT).source(searchSourceBuilder); List<Map<String, Object>> list = new ArrayList<>(); try { SearchResponse searchResponse = client.search(request, EsConfig.COMMON_OPTIONS); for (SearchHit s : searchResponse.getHits().getHits()) { // Map<String, Object> sourceAsMap = s.getSourceAsMap(); list.add(sourceAsMap); } } catch (IOException e) { e.printStackTrace(); } if (list.size() <= 0) { response.setCode("201"); response.setMessage("查询数据为空!"); return response; } response.setResponse(list); return response; } /** * 1:ik_smart:做最粗粒度的拆分;2:ik_max_word:做最细粒度的拆分 * @param barequest * @return */ public BaseResponse queryIk_max_word(BaseRequest<ClassificationOfDiseases> barequest) { BaseResponse response = BaseResponse.success(); // if (null == barequest || barequest.getRequest() == null) { return BaseResponse.error(); } SearchRequest request = new SearchRequest(CLASSIFICATION_OF_DISEASES); ClassificationOfDiseases ofDiseases = barequest.getRequest(); String diseasesName = ofDiseases.getDiseasesName(); BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery(); //ik_smart 为最少切分 //ik_max_word为细粒度划分!会去匹配字典! MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("diseasesName", diseasesName).analyzer("ik_smart"); SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); //分页 searchSourceBuilder.from(0).size(100); searchSourceBuilder.query(boolQueryBuilder); searchSourceBuilder.query(matchQueryBuilder); // request.searchType(SearchType.DEFAULT).source(searchSourceBuilder); List<Map<String, Object>> list = new ArrayList<>(); try { SearchResponse searchResponse = client.search(request, EsConfig.COMMON_OPTIONS); for (SearchHit s : searchResponse.getHits().getHits()) { Map<String, Object> sourceAsMap = s.getSourceAsMap(); list.add(sourceAsMap); } } catch (IOException e) { e.printStackTrace(); } if (list.size() <= 0) { response.setCode("201"); response.setMessage("查询数据为空!"); return response; } response.setResponse(list); return response; } /** * 查询疾病库 中的症状与疾病名称 * @param request * @return */ public BaseResponse< List<Map<String, Object>>> refer(BaseRequest<Map<String, Object>> request){ BaseResponse response = BaseResponse.success(); if (null == request || request.getRequest() == null) { response.setCode("201"); response.setMessage("请求数据异常!"); return response; } //检索的内容 String name=(String)request.getRequest().get("name"); SearchRequest req = new SearchRequest(CLASSIFICATION_OF_DISEASES); BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery(); boolQueryBuilder.filter(QueryBuilders.multiMatchQuery(name, "diseasesName", "singsAndSymptoms" )); SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); //根据中文分词进行查询 //searchSourceBuilder.query(matchQueryBuilder); //分页 searchSourceBuilder.from(0).size(100); searchSourceBuilder.query(boolQueryBuilder); req.searchType(SearchType.DEFAULT).source(searchSourceBuilder); List<Map<String, Object>> list = new ArrayList<>(); SearchHit[] hits1 = null; try { SearchResponse searchResponse = client.search(req, EsConfig.COMMON_OPTIONS); for (SearchHit s : searchResponse.getHits().getHits()) { Map<String, Object> sourceAsMap = s.getSourceAsMap(); list.add(sourceAsMap); } } catch (IOException e) { e.printStackTrace(); } response.setResponse(list); return response; } /** 查询全部 * @param barequest * @return */ public BaseResponse query(BaseRequest<ClassificationOfDiseases> barequest) { if (null == barequest || barequest.getRequest() == null) { return BaseResponse.error(); } ClassificationOfDiseases ofDiseases = barequest.getRequest(); String diseasesName = ofDiseases.getDiseasesName(); String andPathology = ofDiseases.getEtiologyAndPathology(); String administrativeOffice = ofDiseases.getAdministrativeOffice(); String briefIntroduction = ofDiseases.getBriefIntroduction(); String cure = ofDiseases.getCure(); String diagnose = ofDiseases.getDiagnose(); String examine = ofDiseases.getExamine(); String prevent = ofDiseases.getPrevent(); //String prognosis = ofDiseases.getPrognosis(); String singsAndSymptoms = ofDiseases.getSingsAndSymptoms(); String typeName = ofDiseases.getTypeName(); BaseResponse response = BaseResponse.success(); SearchRequest request = new SearchRequest(CLASSIFICATION_OF_DISEASES); BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery(); //term的查询是代表完全匹配,搜索之前不进行分词 //terms和term一样,不进行分词。terms针对一个字段包含多个值得时候使用类似 IN //或者 //boolQueryBuilder.should(QueryBuilders.termQuery("diseaseReason",diseaseReason)); //并且 if (!StringUtils.isEmpty(diseasesName)) { boolQueryBuilder.must(QueryBuilders.matchQuery("diseasesName", diseasesName)); } //并且 if (!StringUtils.isEmpty(andPathology)) { boolQueryBuilder.must(QueryBuilders.matchQuery("andPathology", andPathology)); } /* RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("typeName").from(typeName); // if (cure != null && cure > 0) { rangeQueryBuilder.to(cure); }*/ //boolQueryBuilder.filter(rangeQueryBuilder); /* Map<String, String> queryList =new HashMap<String, String>(); queryList.put("singsAndSymptoms","撒大声地自行车道三"); for (Map.Entry<String, String> entry :queryList.entrySet()) { boolQueryBuilder.should(QueryBuilders.matchPhraseQuery(entry.getKey(),entry.getValue())); }*/ //根据中文分词进行查询 //MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("diseasesName",diseasesName).analyzer("ik_smart"); if (!StringUtils.isEmpty(diseasesName)) { //不分词查 //boolQueryBuilder.filter(QueryBuilders.prefixQuery("diseasesName.keyword", diseasesName)); //boolQueryBuilder.filter(QueryBuilders.fuzzyQuery("diseasesName", diseasesName)); //boolQueryBuilder.should(QueryBuilders.termQuery("andPathology", andPathology)); // boolQueryBuilder.should(QueryBuilders.termQuery("administrativeOffice", administrativeOffice)); // boolQueryBuilder.should(QueryBuilders.termQuery("briefIntroduction", briefIntroduction)); // boolQueryBuilder.should(QueryBuilders.termQuery("cure", cure)); // boolQueryBuilder.should(QueryBuilders.termQuery("diagnose", diagnose)); // boolQueryBuilder.should(QueryBuilders.termQuery("examine", examine)); // boolQueryBuilder.should(QueryBuilders.termQuery("prevent", prevent)); // boolQueryBuilder.should(QueryBuilders.termQuery("prognosis", prognosis)); // boolQueryBuilder.should(QueryBuilders.termQuery("singsAndSymptoms", singsAndSymptoms)); // boolQueryBuilder.should(QueryBuilders.termQuery("typeName", diseasesName)); //boolQueryBuilder.should(QueryBuilders.termQuery("diseasName",diseasName)); //boolQueryBuilder.must(QueryBuilders.matchQuery("diseasesName", diseasesName)); } //prognosis满足模糊匹配prognosis字段 //boolQueryBuilder.filter(QueryBuilders.matchQuery("prognosis", prognosis)); //匹配 唐人 或者 2号 //boolQueryBuilder.must(QueryBuilders.matchQuery("prognosis", "唐人 2号").operator(Operator.OR)); //匹配 唐人 并且 2号 //boolQueryBuilder.must(QueryBuilders.matchQuery("prognosis", "唐人 2号").operator(Operator.AND)); //multi_match 多个字段field匹配一个值,模糊查询 boolQueryBuilder.filter(QueryBuilders.multiMatchQuery(diseasesName, "diseasesName", "andPathology", "administrativeOffice", "briefIntroduction", "cure", "diagnose", "examine", "prevent", "prognosis", "singsAndSymptoms", "typeName", "diseasName", "diseasesName")); SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); //根据中文分词进行查询 //searchSourceBuilder.query(matchQueryBuilder); //分页 searchSourceBuilder.from(0).size(100); searchSourceBuilder.query(boolQueryBuilder); //searchSourceBuilder 高亮设置 searchSourceBuilder.highlighter(getHighlightBuilder()); request.searchType(SearchType.DEFAULT).source(searchSourceBuilder); List<Map<String, Object>> list = new ArrayList<>(); SearchHit[] hits1 = null; try { SearchResponse searchResponse = client.search(request, EsConfig.COMMON_OPTIONS); for (SearchHit s : searchResponse.getHits().getHits()) { Map<String, Object> sourceAsMap = s.getSourceAsMap(); Map<String, HighlightField> highlightFieldsMap = s.getHighlightFields(); //获取高亮查询的结果并覆盖正常查询到的数据 sourceAsMap = getHighLightMap(sourceAsMap, highlightFieldsMap); list.add(sourceAsMap); } } catch (IOException e) { e.printStackTrace(); } response.setResponse(list); return response; } /** * 高亮设置 * * @return */ private HighlightBuilder getHighlightBuilder() { HighlightBuilder highlightBuilder = new HighlightBuilder(); highlightBuilder.preTags("<font color='#e75213'>"); highlightBuilder.postTags("</font>"); /** * highlighterType可选:unified,plain和fvh * unified : 使用Lucene的统一highlighter。 * 这个突出显示器将文本分成句子,并使用BM25算法对单个句子进行评分, * 就好像它们是语料库中的文档一样。它还支持准确的短语和多项(模糊,前缀,正则表达式)突出显示 * *plain highlighter最适合在单一领域突出简单的查询匹配。 * 为了准确反映查询逻辑,它会创建一个微小的内存索引, * 并通过Lucene的查询执行计划程序重新运行原始查询条件, * 以访问当前文档的低级匹配信息。对于需要突出显示的每个字段和每个文档都会 * 重复此操作。如果要在复杂查询的大量文档中突出显示很多字段, * 我们建议使用unified highlighter postings或term_vector字段 * *fvh highlighter使用Lucene的Fast Vector highlighter。此突出显示器可用于映射中term_vector设置为的 * 字段with_positions_offsets。Fast Vector highlighter */ highlightBuilder.highlighterType("unified"); /** * 这只高亮字段,我这里设置为要查询的字段一致 */ highlightBuilder .field("diseasesName") .field("andPathology") .field("administrativeOffice") .field("briefIntroduction") .field("cure") .field("diagnose") .field("examine") .field("prevent") .field("prognosis") .field("singsAndSymptoms") .field("typeName"); //如果要多个字段高亮,这项要为false highlightBuilder.requireFieldMatch(false); /** * fragmentSize 设置要显示出来的fragment文本判断的长度,默认是100 * numOfFragments 代表要显示几处高亮(可能会搜出多段高亮片段)。默认是5 * noMatchSize 即使字段中没有关键字命中,也可以返回一段文字,该参数表示从开始多少个字符被返回 */ //highlightBuilder.fragmentSize(size).numOfFragments(3).noMatchSize(100); return highlightBuilder; } /** * 高亮结果返回 * 正常查询和高亮查询分开返回的,也就是高亮部分数据不会影响正常数据 * 这里要用高亮数据覆盖正常返回数据,这样返回前端就是匹配的都是高亮显示了 **/ private Map<String, Object> getHighLightMap(Map<String, Object> map, Map<String, HighlightField> highlightFields) { HighlightField diseasesName = highlightFields.get("diseasesName"); HighlightField andPathology = highlightFields.get("andPathology"); HighlightField administrativeOffice = highlightFields.get("administrativeOffice"); HighlightField briefIntroduction = highlightFields.get("briefIntroduction"); HighlightField cure = highlightFields.get("cure"); HighlightField diagnose = highlightFields.get("diagnose"); HighlightField examine = highlightFields.get("examine"); HighlightField prevent = highlightFields.get("prevent"); HighlightField prognosis = highlightFields.get("prognosis"); HighlightField singsAndSymptoms = highlightFields.get("singsAndSymptoms"); HighlightField typeName = highlightFields.get("typeName"); if (diseasesName != null) { map.put("diseasesName", diseasesName.fragments()[0].string()); } if (andPathology != null) { map.put("andPathology", andPathology.fragments()[0].string()); } if (administrativeOffice != null) { map.put("administrativeOffice", administrativeOffice.fragments()[0].string()); } if (briefIntroduction != null) { map.put("briefIntroduction", briefIntroduction.fragments()[0].string()); } if (cure != null) { map.put("cure", cure.fragments()[0].string()); } if (diagnose != null) { map.put("diagnose", diagnose.fragments()[0].string()); } if (examine != null) { map.put("examine", examine.fragments()[0].string()); } if (prevent != null) { map.put("prevent", prevent.fragments()[0].string()); } if (prognosis != null) { map.put("prognosis", prognosis.fragments()[0].string()); } if (singsAndSymptoms != null) { map.put("singsAndSymptoms", singsAndSymptoms.fragments()[0].string()); } if (typeName != null) { map.put("typeName", typeName.fragments()[0].string()); } return map; } /** * 这里以最多3个字段来分组统计(可以是1个,2个,3个 来做统计) **/ public Map<String, Object> multiField3Aggregation(String field1, String field2, String field3) { Map<String, Object> data = new HashMap<>(); data.clear(); SearchRequest request = new SearchRequest(); request.indices(CLASSIFICATION_OF_DISEASES); SearchSourceBuilder ssb = new SearchSourceBuilder(); ssb = getDifferentFieldRequestResult(ssb, field1, field2, field3, 500); request.source(ssb); SearchResponse response = null; Map<String, Long> resultMap = new HashMap<>(); resultMap.clear(); try { response = client.search(request, EsConfig.COMMON_OPTIONS); // 从这里分支 获取返回参数 resultMap = getDifferentFieldResponseResult(field1, field2, field3, response); Map<String, Object> arrAfterSort = getArrAfterSort(resultMap, 500); return arrAfterSort; } catch (IOException e) { e.printStackTrace(); } return null; } /** * 分组统计的核心部分 * numbers是要返回的数据条数 **/ private SearchSourceBuilder getDifferentFieldRequestResult(SearchSourceBuilder ssb, String groupField, String groupNum2Field, String groupNum3Field, Integer numbers) { if (!org.apache.commons.lang.StringUtils.isBlank(groupField) && org.apache.commons.lang.StringUtils.isBlank(groupNum2Field) && org.apache.commons.lang.StringUtils.isBlank(groupNum3Field)) { ssb.aggregation(AggregationBuilders .terms(groupField + "Agg") .field(groupField + ".keyword") .order(BucketOrder.count(false)) .size(numbers)); } else if (!StringUtils.isBlank(groupField) && !StringUtils.isBlank(groupNum2Field) && StringUtils.isBlank(groupNum3Field)) { if (groupField.equalsIgnoreCase(groupNum2Field)) { throw new RuntimeException("查询字段为空!"); } TermsAggregationBuilder field1Aggregation = getTermsAggregationBuilder(groupField); TermsAggregationBuilder field2Aggregation = getTermsAggregationBuilder(groupNum2Field); //里外都去23,23x23=529 满足最多查500条的最小数的平方 field1Aggregation.subAggregation(field2Aggregation.order(BucketOrder.count(false)).size(23)); ssb.aggregation(field1Aggregation.order(BucketOrder.count(false)). size(50)); } else if (!StringUtils.isBlank(groupField) && !StringUtils.isBlank(groupNum2Field) && !StringUtils.isBlank(groupNum3Field)) { if (groupField.equalsIgnoreCase(groupNum2Field) || groupField.equalsIgnoreCase(groupNum3Field) || groupNum2Field.equalsIgnoreCase(groupNum3Field)) { throw new RuntimeException("查询字段为空!"); } TermsAggregationBuilder field1Aggregation = getTermsAggregationBuilder(groupField); TermsAggregationBuilder field2Aggregation = getTermsAggregationBuilder(groupNum2Field); TermsAggregationBuilder field3Aggregation = getTermsAggregationBuilder(groupNum3Field); field2Aggregation.subAggregation(field3Aggregation.order(BucketOrder.count(false)).size(8)); field1Aggregation.subAggregation(field2Aggregation.order(BucketOrder.count(false)).size(8)); ssb.aggregation(field1Aggregation.order(BucketOrder.count(false)).size(8)); } else if (!StringUtils.isBlank(groupField) && StringUtils.isBlank(groupNum2Field) && !StringUtils.isBlank(groupNum3Field)) { throw new RuntimeException("查询字段为空!"); } return ssb; } /** * 传入字段获取TermsAggregationBuilder对象 */ private TermsAggregationBuilder getTermsAggregationBuilder(String fieldName) { TermsAggregationBuilder fieldNameAggregation = AggregationBuilders .terms(fieldName + "Agg") .field(fieldName + ".keyword"); return fieldNameAggregation; } /** * 根据 不同分组字段个数 进行分组 返回参数 * * @param groupField * @param groupNum2Field * @param groupNum3Field * @param response * @return */ private Map<String, Long> getDifferentFieldResponseResult( String groupField, String groupNum2Field, String groupNum3Field, SearchResponse response) { Map<String, Long> map = new HashMap<>(); map.clear(); if (!StringUtils.isBlank(groupField) && StringUtils.isBlank(groupNum2Field) && StringUtils.isBlank(groupNum3Field)) { Aggregations aggregations = response.getAggregations(); ParsedStringTerms parsedStringTerms = aggregations.get(groupField + "Agg"); List<? extends Terms.Bucket> buckets = parsedStringTerms.getBuckets(); for (Terms.Bucket bucket : buckets) { String key = bucket.getKey().toString(); long docCount = bucket.getDocCount(); map.put(key, docCount); } } else if (!StringUtils.isBlank(groupField) && !StringUtils.isBlank(groupNum2Field) && StringUtils.isBlank(groupNum3Field)) { Terms agg = response.getAggregations().get(groupField + "Agg"); for (Terms.Bucket entry : agg.getBuckets()) { String key = entry.getKey().toString(); long docCount = entry.getDocCount(); Terms Terms2 = entry.getAggregations().get(groupNum2Field + "Agg"); for (Terms.Bucket entry2 : Terms2.getBuckets()) { String key2 = entry2.getKey().toString(); long docCount2 = entry2.getDocCount(); map.put(key + "," + key2, docCount2); } } } else if (!StringUtils.isBlank(groupField) && !StringUtils.isBlank(groupNum2Field) && !StringUtils.isBlank(groupNum3Field)) { Terms agg = response.getAggregations().get(groupField + "Agg"); for (Terms.Bucket entry : agg.getBuckets()) { String key1 = entry.getKey().toString(); long docCount1 = entry.getDocCount(); Terms terms = entry.getAggregations().get(groupNum2Field + "Agg"); for (Terms.Bucket en : terms.getBuckets()) { String key2 = en.getKey().toString(); long docCount2 = en.getDocCount(); Terms term = en.getAggregations().get(groupNum3Field + "Agg"); for (Terms.Bucket ent : term.getBuckets()) { String key3 = ent.getKey().toString(); long docCount3 = ent.getDocCount(); map.put(key1 + "," + key2 + "," + key3, docCount3); } } } } return map; } public static Map<String, Object> getArrAfterSort(Map<String, Long> m, int d) { Map<String, Object> map = new HashMap<>(); map.clear(); List<Map.Entry<String, Long>> list = new ArrayList<>(m.entrySet()); Collections.sort(list, (o1, o2) -> { int flag = o1.getValue().compareTo(o2.getValue()); if (flag == 0) { return o1.getKey().compareTo(o2.getKey()); } return flag; }); Long[] valueArr = new Long[list.size()]; String[] keyStr = new String[list.size()]; int i = 0; for (Map.Entry<String, Long> en : list) { valueArr[i] = en.getValue(); keyStr[i] = en.getKey(); i++; } map.put("xAis", keyStr); map.put("yAis", valueArr); return map; } /** * 类似mysql的 where id in (id1,id2,id3) * * @param args */ public Map<String, Object> maIn(String[] args) { SearchRequest request = new SearchRequest(); request.indices(CLASSIFICATION_OF_DISEASES); SearchSourceBuilder builder = new SearchSourceBuilder(); BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder(); //核心部分 boolQueryBuilder.filter(QueryBuilders.idsQuery() .addIds(args[0])); builder.query(boolQueryBuilder); request.source(builder); List<Map<String, Object>> list = new ArrayList<>(); Map<String, Object> map = new HashMap<>(); try { SearchResponse response = client.search(request, EsConfig.COMMON_OPTIONS); SearchHit[] searchHits = response.getHits().getHits(); for (SearchHit hit : searchHits) { Map<String, Object> sourceAsMap = hit.getSourceAsMap(); list.add(sourceAsMap); } map.put("data", list); } catch (IOException e) { e.printStackTrace(); } return map; } //创建索引方法,传入索引名和类型名 public BaseResponse reCreateIndex(String index, String type) { BaseResponse response = BaseResponse.success(); return response; } /** * 新增修改 * * @param indexName * @param type * @param id * @param jsonStr */ public void addData(String indexName, String type, String id, String jsonStr) { try { // 1、创建索引请求 //索引 // mapping type //文档id IndexRequest request = new IndexRequest(indexName, type, id); //文档id // 2、准备文档数据 // 直接给JSON串 request.source(jsonStr, XContentType.JSON); //4、发送请求 IndexResponse indexResponse = null; try { // 同步方式 indexResponse = client.index(request, EsConfig.COMMON_OPTIONS); } catch (Exception e) { // 捕获,并处理异常 //判断是否版本冲突、create但文档已存在冲突 /*if (e.status() == RestStatus.CONFLICT) { log.info("冲突了,请在此写冲突处理逻辑!" + e.getDetailedMessage()); }*/ } //5、处理响应 if (indexResponse != null) { String index1 = indexResponse.getIndex(); String type1 = indexResponse.getType(); String id1 = indexResponse.getId(); long version1 = indexResponse.getVersion(); if (indexResponse.getResult() == DocWriteResponse.Result.CREATED) { log.info("======新增文档成功!=======" + index1 + type1 + id1 + version1); } else if (indexResponse.getResult() == DocWriteResponse.Result.UPDATED) { log.info("=====修改文档成功!========"); } // 分片处理信息 ReplicationResponse.ShardInfo shardInfo = indexResponse.getShardInfo(); if (shardInfo.getTotal() != shardInfo.getSuccessful()) { log.info("========分片处理信息.....======"); } // 如果有分片副本失败,可以获得失败原因信息 if (shardInfo.getFailed() > 0) { for (ReplicationResponse.ShardInfo.Failure failure : shardInfo.getFailures()) { String reason = failure.reason(); log.info("======副本失败原因:======" + reason); } } } } catch (Exception e) { e.printStackTrace(); } } /** * 批量插入 * * @param indexName * @param type * @param idName * @param list */ public void bulkDate(String indexName, String type, String idName, List<Map<String, Object>> list) { try { if (null == list || list.size() <= 0) { return; } if (StringUtils.isBlank(indexName) || StringUtils.isBlank(idName) || StringUtils.isBlank(type)) { return; } BulkRequest request = new BulkRequest(); for (Map<String, Object> map : list) { if (map.get(idName) != null) { request.add(new IndexRequest(indexName, type, String.valueOf(map.get(idName))) .source(map, XContentType.JSON)); } } // 2、可选的设置 request.timeout("2m"); request.setRefreshPolicy("wait_for"); request.waitForActiveShards(2); //3、发送请求 // 同步请求 BulkResponse bulkResponse = client.bulk(request, EsConfig.COMMON_OPTIONS); //4、处理响应 if (bulkResponse != null) { for (BulkItemResponse bulkItemResponse : bulkResponse) { DocWriteResponse itemResponse = bulkItemResponse.getResponse(); if (bulkItemResponse.getOpType() == DocWriteRequest.OpType.INDEX || bulkItemResponse.getOpType() == DocWriteRequest.OpType.CREATE) { IndexResponse indexResponse = (IndexResponse) itemResponse; log.info("======新增成功,{}=========" + indexResponse.toString()); } else if (bulkItemResponse.getOpType() == DocWriteRequest.OpType.UPDATE) { UpdateResponse updateResponse = (UpdateResponse) itemResponse; log.info("======修改成功,{}=========" + updateResponse.toString()); } else if (bulkItemResponse.getOpType() == DocWriteRequest.OpType.DELETE) { DeleteResponse deleteResponse = (DeleteResponse) itemResponse; log.info("======删除成功,{}=========" + deleteResponse.toString()); } } } } catch (IOException e) { e.printStackTrace(); } } /** * 前缀查询,可以通过一个关键字去指定一个field的前缀,从而查询到指定文档 * * @param args */ public void mains(String[] args) { SearchRequest request = new SearchRequest(); request.indices(CLASSIFICATION_OF_DISEASES); SearchSourceBuilder builder = new SearchSourceBuilder(); BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder(); //模糊查询:输入字符大概,es就会根据输入内容去匹配结果(有一点错别字也可以查到,一般不推荐这种方式使用) //boolQueryBuilder.filter( QueryBuilders.fuzzyQuery("name" ,"王")); //前缀查询 可以通过一个关键字去指定一个field的前缀,从而查询到指定文档 boolQueryBuilder.filter(QueryBuilders.prefixQuery("name.keyword", "王")); builder.query(boolQueryBuilder); request.source(builder); List<Map<String, Object>> list = new ArrayList<>(); Map<String, Object> map = new HashMap<>(); try { SearchResponse response = client.search(request, EsConfig.COMMON_OPTIONS); SearchHit[] searchHits = response.getHits().getHits(); for (SearchHit hit : searchHits) { Map<String, Object> sourceAsMap = hit.getSourceAsMap(); list.add(sourceAsMap); } map.put("data", list); // return R.ok("查询成功!").put("result", map); } catch (IOException e) { e.printStackTrace(); } } /** * 通配查询: 与MYSQL中的like是一样的,在查询时可以指定通配符和占位符 * *是通配符 ?是占位符 * * @param args */ public void mainss(String[] args) { SearchRequest request = new SearchRequest(); request.indices(CLASSIFICATION_OF_DISEASES); SearchSourceBuilder builder = new SearchSourceBuilder(); BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder(); //boolQueryBuilder.filter(QueryBuilders.wildcardQuery("name.keyword","hz")); boolQueryBuilder.filter(QueryBuilders.wildcardQuery("name.keyword", "hh??")); // range查询:只针对数值类型范围查询{大于:gt,小于:lt,大于等于:gte,小于等于:lte} // boolQueryBuilder.filter(QueryBuilders.rangeQuery("height").gt(170).lte(190)); //regexp查询(prefix、wildcard、regexp、fuzzy查询效率低,谨慎使用,尽量避免) //boolQueryBuilder.filter(QueryBuilders.regexpQuery("age","2[0-9]{1}")); builder.query(boolQueryBuilder); // 分页查询 builder.from(0).size(20); request.source(builder); //log.info("======="+builder); List<Map<String, Object>> list = new ArrayList<>(); Map<String, Object> map = new HashMap<>(); try { SearchResponse response = client.search(request, EsConfig.COMMON_OPTIONS); SearchHit[] searchHits = response.getHits().getHits(); for (SearchHit hit : searchHits) { Map<String, Object> sourceAsMap = hit.getSourceAsMap(); list.add(sourceAsMap); } map.put("data", list); //return R.ok("查询成功!").put("result", map); } catch (IOException e) { e.printStackTrace(); } } //复合过滤器,将多个查询条件以一定的逻辑组合在一起 //must:-----类似mysql的and //must_not:类似mysql的not //should :----类似mysql的or java例子 public void mainsss(String[] args) { SearchRequest request = new SearchRequest(); request.indices(CLASSIFICATION_OF_DISEASES); SearchSourceBuilder builder = new SearchSourceBuilder(); BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder(); //或者 boolQueryBuilder.should(QueryBuilders.termQuery("job", "程序员")); boolQueryBuilder.should(QueryBuilders.termQuery("job", "教师")); //不是(非) boolQueryBuilder.mustNot(QueryBuilders.termQuery("name", "张三")); //并且 boolQueryBuilder.must(QueryBuilders.matchQuery("address", "百草")); boolQueryBuilder.must(QueryBuilders.matchQuery("address", "13")); builder.query(boolQueryBuilder); request.source(builder); List<Map<String, Object>> list = new ArrayList<>(); Map<String, Object> map = new HashMap<>(); try { SearchResponse response = client.search(request, EsConfig.COMMON_OPTIONS); SearchHit[] searchHits = response.getHits().getHits(); for (SearchHit hit : searchHits) { Map<String, Object> sourceAsMap = hit.getSourceAsMap(); list.add(sourceAsMap); } map.put("data", list); // return R.ok("查询成功!").put("result", map); } catch (IOException e) { e.printStackTrace(); } } /** * @param args */ public void ma(String[] args) { //1.创建DeleteByQueryRequest DeleteByQueryRequest request = new DeleteByQueryRequest(); request.indices(CLASSIFICATION_OF_DISEASES); //2、指定检索条件 request.setQuery(QueryBuilders.rangeQuery("height").lte(170)); try { //执行删除 BulkByScrollResponse response = client.deleteByQuery(request, EsConfig.COMMON_OPTIONS); //log.info("删除成功,返回:"+response); } catch (IOException e) { e.printStackTrace(); } } /** * boosting查询 * 帮助我们去影响查询后的分数score * *positive 只有匹配到positive的查询内容,才会放到结果集 * *negative 同时匹配上positive和negative,那么会降低文档得分 negative_boost指定系数,小于1. * * @param args */ public void mn(String[] args) { SearchRequest request = new SearchRequest(); request.indices(CLASSIFICATION_OF_DISEASES); SearchSourceBuilder builder = new SearchSourceBuilder(); BoostingQueryBuilder boostingQueryBuilder = QueryBuilders.boostingQuery( QueryBuilders.matchQuery("address", "百"), QueryBuilders.matchQuery("name", "珊") ).negativeBoost(0.3f); builder.query(boostingQueryBuilder); request.source(builder); List<Map<String, Object>> list = new ArrayList<>(); Map<String, Object> map = new HashMap<>(); try { SearchResponse response = client.search(request, EsConfig.COMMON_OPTIONS); SearchHit[] searchHits = response.getHits().getHits(); for (SearchHit hit : searchHits) { Map<String, Object> sourceAsMap = hit.getSourceAsMap(); list.add(sourceAsMap); } map.put("data", list); // return R.ok("查询成功!").put("result", map); } catch (IOException e) { e.printStackTrace(); } } // filter // query:根据查询条件,去计算文档匹配度得到一个分数,并根据分数进行排序,不做缓存 // filter:根据查询条件去查询文档,不去计算分数,而且filter会对经常被过滤的数据进行缓存 public void maghin(String[] args) { SearchRequest request = new SearchRequest(); request.indices(CLASSIFICATION_OF_DISEASES); SearchSourceBuilder builder = new SearchSourceBuilder(); BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder(); boolQueryBuilder.filter(QueryBuilders.termQuery("name.keyword", "王思思")); builder.query(boolQueryBuilder); request.source(builder); List<Map<String, Object>> list = new ArrayList<>(); Map<String, Object> map = new HashMap<>(); try { SearchResponse response = client.search(request, EsConfig.COMMON_OPTIONS); SearchHit[] searchHits = response.getHits().getHits(); for (SearchHit hit : searchHits) { Map<String, Object> sourceAsMap = hit.getSourceAsMap(); list.add(sourceAsMap); } map.put("data", list); //return R.ok("查询成功!").put("result", map); } catch (IOException e) { e.printStackTrace(); } } /** * 高亮就是用户输入关键字,以一定特殊样式展示给用户,让用户知道为什么这个结果被检索出来 * 高亮展示数据,本身就是文档中的一个field,单独将field以highlight的形式返回给你 * ES提供一个highlight属性,和query同级别 * 1、fragment_size:指定高亮数据展示多少个字符回来 * 2、pre_tags:指定前缀标签<font color="red"> * 3、post_tags:指定后缀标签</font> * 4、fields:指定哪个field以高亮形式返回 * * @param keyWord * @return */ public Map<String, Object> getKeyWordHighLightQuery(String keyWord) { Integer start = 0; Integer limit = 10; SearchRequest request = new SearchRequest(); request.indices(CLASSIFICATION_OF_DISEASES); SearchSourceBuilder ssb = new SearchSourceBuilder(); BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder(); if (!StringUtils.isBlank(keyWord)) { /** * QueryBuilders.multiMatchQuery 多个字段field匹配一个值,模糊查询: * 第一参数是输入的要查询的值,后面的都是要匹配的字段 */ boolQueryBuilder .filter(QueryBuilders.multiMatchQuery( keyWord, "companyCode", "loginType", "userId", "appid", "loginIp", "unitCode", "id", "userType", "isInWhitlelist", "env")); } ssb.query(boolQueryBuilder); ssb.trackTotalHits(true); ssb.highlighter(getHighlightBuilder()); request.source(ssb); SearchResponse response = null; List<Map<String, Object>> list = new ArrayList<>(); Map<String, Object> map = new HashMap<>(); list.clear(); map.clear(); log.info("==输出执行搜索的语句:====" + request); try { response = client.search(request, EsConfig.COMMON_OPTIONS); long total = response.getHits().getTotalHits().value; Integer totalPage = (int) Math.ceil((double) total / limit); map.put("currPage", start + 1); map.put("pageSize", limit); map.put("totalPage", totalPage); map.put("totalCount", total); SearchHit[] searchHits = response.getHits().getHits(); for (SearchHit hit : searchHits) { Map<String, Object> sourceAsMap = hit.getSourceAsMap(); Map<String, HighlightField> highlightFieldsMap = hit.getHighlightFields(); sourceAsMap = getHighLightMap(sourceAsMap, highlightFieldsMap); list.add(sourceAsMap); } map.put("data", list); return map; } catch (IOException e) { e.printStackTrace(); } return null; } //ES提供了多种多样的聚合查询, public void heightAvgMain(String[] args) { SearchRequest request = new SearchRequest(); request.indices(CLASSIFICATION_OF_DISEASES); SearchSourceBuilder builder = new SearchSourceBuilder(); //按照名字聚合 builder.aggregation(AggregationBuilders.terms("agg").field("name.keyword").size(10)); //按照平均身高聚合 builder.aggregation(AggregationBuilders.avg("heightAvg").field("height")); request.source(builder); List<Map<String, Object>> list = new ArrayList<>(); Map<String, Object> map = new HashMap<>(); Map<String, Object> mapAgg = new HashMap<>(); try { SearchResponse response = client.search(request, EsConfig.COMMON_OPTIONS); SearchHit[] searchHits = response.getHits().getHits(); for (SearchHit hit : searchHits) { Map<String, Object> sourceAsMap = hit.getSourceAsMap(); list.add(sourceAsMap); } /** * 获取聚合信息 */ Aggregations aggregations = response.getAggregations(); Terms terms = aggregations.get("agg"); for (Terms.Bucket bucket : terms.getBuckets()) { String keyAsString = bucket.getKeyAsString(); long docCount = bucket.getDocCount(); mapAgg.put(keyAsString, docCount); } //获取平均值 Avg avg = aggregations.get("heightAvg"); map.put("mapAgg", mapAgg); map.put("avg", avg.getValue()); map.put("result", list); //return R.ok("查询成功!").put("result", map); } catch (IOException e) { e.printStackTrace(); } } }