java使用elasticsearch进行多个条件模糊查询
文章说明:
1、本篇文章,本人会从java连接elasticsearch到查询结果生成并映射到具体实体类(涵盖分页功能)
2、代码背景:elasticsearch版本为:5.2.0;
3、本人以下代码是分别从两个索引中查询数据,再将两个数据进行整合,如果大家只需要分组查询,那么则选取文章中的分组查询部分代码
4、本人的实体类主要是按照layUI分页框架进行设计;实体大家可以根据自己的具体需求进行设计
一、java连接elasticsearch工具类
public class ESClientConnectionUtil { public static TransportClient client=null; public final static String HOST = "192.168.200.200"; //服务器部署ip 根据自己ip进行更改 public final static Integer PORT = 9301; //端口 public static TransportClient getESClient(){ System.setProperty("es.set.netty.runtime.available.processors", "false"); if (client == null) { synchronized (ESClientConnectionUtil.class) { try { //设置集群名称 Settings settings = Settings.builder().put("cluster.name", "es5").put("client.transport.sniff", true).build(); //创建client client = new PreBuiltTransportClient(settings).addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName(HOST), PORT)); } catch (Exception ex) { ex.printStackTrace(); System.out.println(ex.getMessage()); } } } return client; } public static TransportClient getESClientConnection(){ if (client == null) { System.setProperty("es.set.netty.runtime.available.processors", "false"); try { //设置集群名称 Settings settings = Settings.builder().put("cluster.name", "es5").put("client.transport.sniff", true).build(); //创建client client = new PreBuiltTransportClient(settings).addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName(HOST), PORT)); } catch (Exception ex) { ex.printStackTrace(); System.out.println(ex.getMessage()); } } return client; } //判断索引是否存在 public static boolean judgeIndex(String index){ client= getESClientConnection(); IndicesAdminClient adminClient; //查询索引是否存在 adminClient= client.admin().indices(); IndicesExistsRequest request = new IndicesExistsRequest(index); IndicesExistsResponse responses = adminClient.exists(request).actionGet(); if (responses.isExists()) { return true; } return false; } }
二、实体类
(一)分页实体总类
public class KnowledgeTopicListDTO { private Long totalCount;//总条数 private Integer page;//页数 private Integer limit;//每页查询条数 private List<KnowledgeTopicDTO> topicDTOList;//每页显示数据的对象集合 public Long getTotalCount() { return totalCount; } public void setTotalCount(Long totalCount) { this.totalCount = totalCount; } public Integer getPage() { return page; } public void setPage(Integer page) { this.page = page; } public Integer getLimit() { return limit; } public void setLimit(Integer limit) { this.limit = limit; } public List<KnowledgeTopicDTO> getTopicDTOList() { return topicDTOList; } public void setTopicDTOList(List<KnowledgeTopicDTO> topicDTOList) { this.topicDTOList = topicDTOList; } }
(二)页面显示数据对象实体
public class KnowledgeTopicDTO { private Long id;//知识主题id private String name;//知识主题名称 private Boolean active;//有效无效 true,false private String activeString;//有效无效 private Boolean noSubscription;//是否需要订阅 true,false private String noSubscriptionString;//是否需要订阅 private Long quantity;//数据量 private String _id; private String ids; public String getIds() { return ids; } public void setIds(String ids) { this.ids = ids; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Boolean getActive() { return active; } public void setActive(Boolean active) { this.active = active; } public String getActiveString() { return activeString; } public void setActiveString(String activeString) { this.activeString = activeString; } public Boolean getNoSubscription() { return noSubscription; } public void setNoSubscription(Boolean noSubscription) { this.noSubscription = noSubscription; } public String getNoSubscriptionString() { return noSubscriptionString; } public void setNoSubscriptionString(String noSubscriptionString) { this.noSubscriptionString = noSubscriptionString; } public Long getQuantity() { return quantity; } public void setQuantity(Long quantity) { this.quantity = quantity; } public String get_id() { return _id; } public void set_id(String _id) { this._id = _id; } }
三、后台service层代码
public KnowledgeTopicListDTO selectTopicByName(String name, Integer page, Integer limit) { SearchResponse searchResponse=null; Map<String,Object> map = new HashMap<>(); TransportClient transportClient = ESClientConnectionUtil.getESClientConnection(); SearchRequestBuilder requestBuilder = client.prepareSearch("knowledge").setTypes("knowledge_theme"); // 声明where条件 BoolQueryBuilder qbs = QueryBuilders.boolQuery(); /**此处使用模糊匹配查询 类比数据库中 like*/ QueryBuilder qb1 = QueryBuilders.matchPhraseQuery("name", name); BoolQueryBuilder bqb1 = QueryBuilders.boolQuery().must(qb1); qbs.must(bqb1); requestBuilder.setQuery(qbs); int num=limit*(page-1); SearchResponse response = requestBuilder.setFrom(0).setSize(10).execute().actionGet(); //获取总条数 // long totalCount = searchResponse.getHits().getTotalHits(); List<KnowledgeTopicDTO> list = new ArrayList<KnowledgeTopicDTO>(); for (SearchHit hit : response.getHits().getHits()) { //获取到当前页的数据 JSONObject obj = new JSONObject().fromObject(hit.getSourceAsString());//将json字符串转换为json对象 KnowledgeTopicDTO topic = (KnowledgeTopicDTO) JSONObject.toBean(obj, KnowledgeTopicDTO.class);//将建json对象转换为Person对象 list.add(topic); } //查询主题总数 Terms terms= ESGroupByUtil.GroupByOne(client,"hottopic","hot","sum","tasktitleid"); list= groupList(list,terms);//调用组合主题总数方法 KnowledgeTopicListDTO knowledgeTopicListDTO = new KnowledgeTopicListDTO(); knowledgeTopicListDTO.setLimit(limit); knowledgeTopicListDTO.setPage(page); knowledgeTopicListDTO.setTopicDTOList(list); return knowledgeTopicListDTO; }
五、根据单个字段分组查询
public class ESGroupByUtil { /** *@description: 根据单个字段分组求和 *@author:cyb *@date: 2018-11-16 17:31 *@param: client ES连接 *@param: indices 索引 *@param: types 类型 *@param: alias 分组求和别名 *@param: DomName 分组目标字段名 *@return: org.elasticsearch.search.aggregations.bucket.terms.Terms */ public static Terms GroupByOne(TransportClient client,String indices,String types,String alias,String DomName){ SearchRequestBuilder sbuilder = client.prepareSearch(indices).setTypes(types); TermsAggregationBuilder termsBuilder = AggregationBuilders.terms(alias).field(DomName); sbuilder.addAggregation(termsBuilder); SearchResponse responses= sbuilder.execute().actionGet(); Terms terms = responses.getAggregations().get(alias); return terms; } }
六 、将分组查询的数据进行整合到已查询到的集合中
/** *@description:将查询的总数合并到list中 *@author:cyb *@date: 2018-11-16 17:51 *@param: list *@param: terms *@return: java.util.List<com.yjlc.platform.bsKnowledge.KnowledgeTopicDTO> */ public List<KnowledgeTopicDTO> groupList(List<KnowledgeTopicDTO> list,Terms terms){ List<BsKnowledgeInfoDTO> lists = new ArrayList<>(); for(int i=0;i<terms.getBuckets().size();i++){ //statistics String id =terms.getBuckets().get(i).getKey().toString();//id Long sum =terms.getBuckets().get(i).getDocCount();//数量 BsKnowledgeInfoDTO bsKnowledgeInfoDTO1 = new BsKnowledgeInfoDTO(); bsKnowledgeInfoDTO1.setId(id); bsKnowledgeInfoDTO1.setSum(sum); lists.add(bsKnowledgeInfoDTO1); System.out.println("=="+ terms.getBuckets().get(i).getDocCount()+"------"+terms.getBuckets().get(i).getKey()); } for(int i=0;i<lists.size();i++){ for(int j=0;j<list.size();j++){ if(lists.get(i).getId().equals(list.get(j).getId())){ list.get(j).setQuantity(lists.get(i).getSum()); } } } return list; }
总结:以上代码是本人的亲自测试通过的,分页后期建议大家不用使用from,size格式,当数据量超过1w的时候,速度会越来越慢,并可能造成宕机。
精准条件查询
MatchPhraseQueryBuilder mpq1 = QueryBuilders .matchPhraseQuery("id",knowledgeId); qbs.must(mpq1);//主题id
模糊条件查询
QueryBuilder qb1 = QueryBuilders.matchPhraseQuery("title", keyword);
qbs.must(qb1);
requestBuilder.setQuery(qbs);