这段代码的功能是查询出es里面的数据进行分页展示,使用的jar版本为2.4
大概流程
添加maven依赖
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>2.4.0</version>
</dependency>
properties属性文件配置
spring.elasticsearch.host=192.168.101.123
spring.elasticsearch.port=9300
spring的配置文件,初始化TransportClient 对象
package com.unioncast.ssp.front.config;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.InetSocketTransportAddress;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import java.net.InetAddress;
import java.net.UnknownHostException;
/**
* ElasticsearchConfig
*
* @author zhangzhe
* @date 2017/2/21 16:33
*/
@Configuration
@PropertySource(value = "classpath:/elasticsearch.properties")
public class ElasticsearchConfig {
@Value("${spring.elasticsearch.host}")
private String host;
@Value("${spring.elasticsearch.port}")
private int port;
private static final Logger LOG = LogManager.getLogger(ElasticsearchConfig.class);
@Bean
public TransportClient elasticsearchClient(){ //向spring注入es的客户端操作对象
TransportClient transportClient = null;
Settings settings = Settings.settingsBuilder()
.put("cluster.name", "bigData-cluster").build();
try {
transportClient = TransportClient
.builder()
.settings(settings)
.build()
.addTransportAddress(
new InetSocketTransportAddress(InetAddress.getByName(host), port)
);
} catch (UnknownHostException e) {
LOG.error("创建elasticsearch客户端失败");
}
LOG.info("创建elasticsearch客户端成功");
return transportClient;
}
}
对数据进行查询操作的实现类
package com.unioncast.ssp.front.service.ssp.elasticsearchData;
import com.unioncast.common.page.Pagination;
import com.unioncast.common.restClient.RestResponse;
import com.unioncast.common.ssp.model.SspAdvertiser;
import com.unioncast.common.ssp.model.SspCreative;
import com.unioncast.ssp.front.service.ssp.SspAdvertiserService;
import com.unioncast.ssp.front.service.ssp.SspCreativeService;
import com.unioncast.ssp.front.service.ssp.SspOrderService;
import com.unioncast.ssp.front.service.ssp.SspPlanService;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.SearchType;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.net.UnknownHostException;
import java.util.*;
/**
* @author zhangzhe
* @date 2017/2/21 10:25
*/
@Component
public class ElasticsearchADReportImpl implements ElasticsearchADReport {
private static final Logger LOG = LogManager.getLogger(ElasticsearchADReportImpl.class);
private static final String INDEX = "hehe"; //es的索引表名称
private static final String TYPE = "kafka_type"; //es的索引类型
private static final Integer PAGESIZE = 10; //分页的每页显示数
private static final String ESC = "ip"; //用于排序的字段
@Resource
TransportClient transportClient; //注入es操作对象
@Resource
SspAdvertiserService sspAdvertiserService;
@Resource
SspOrderService sspOrderService;
@Resource
SspPlanService sspPlanService;
@Resource
SspCreativeService sspCreativeService;
//es查询
public Pagination<Map<String, Object>> esADReport(Long accountId, Long advertiserId, Long orderId, Long planId, Long creativeId,
Integer currentPageNo, String startTime, String endTime)
throws UnknownHostException {
List<Map<String, Object>> list = new ArrayList<>();
Integer totalCount = 0;
QueryBuilder query = QueryBuilders.boolQuery();
//用户ID 这里的matchPhraseQuery代表精确查询,同样使用matchQuery也可以,matchPhrasePrefixQuery代表的是模糊查询
if (accountId != null) {
query = QueryBuilders.boolQuery()
.must(QueryBuilders.matchPhraseQuery("accountId", accountId));
}
//广告主ID
if (advertiserId != null) {
query = QueryBuilders.boolQuery()
.must(QueryBuilders.matchPhraseQuery("advertiserId", advertiserId));
}
//订单ID
if (orderId != null) {
query = QueryBuilders.boolQuery()
.must(QueryBuilders.matchPhraseQuery("orderId", orderId));
}
//计划ID
if (planId != null) {
query = QueryBuilders.boolQuery()
.must(QueryBuilders.matchPhraseQuery("planId", planId));
}
//创意ID
if (creativeId != null) {
query = QueryBuilders.boolQuery()
.must(QueryBuilders.matchPhraseQuery("creativeId", creativeId));
}
//总数
/* SearchResponse rsTotal = transportClient.prepareSearch(INDEX).setTypes(TYPE)
.setSearchType(SearchType.DFS_QUERY_AND_FETCH)
.setQuery(query)
.addSort(ESC, SortOrder.DESC)
.setExplain(true).execute().actionGet();
if (rsTotal != null && rsTotal.getHits().getHits().length != 0) {
totalCount = (int) rsTotal.getHits().getTotalHits();
// System.out.println("totalHits: "+totalHits);
// totalCount=rsTotal.getHits().getHits().length;
// System.out.println("totalCount: "+totalCount);
}*/
//搜索 这里的.setSearchType属性代表索引的查询方式,几种方式的区别我写在末尾
int pageIndex = (currentPageNo - 1) * PAGESIZE;
SearchResponse rs = transportClient.prepareSearch(INDEX).setTypes(TYPE)
.setSearchType(SearchType.DFS_QUERY_THEN_FETCH) //这里非常重要,当初就是因为类型填写错误,导致查询出超出预计结果的数据
.setQuery(query) //查询条件
.addSort(ESC, SortOrder.DESC) //排序,DESC为倒序
.setFrom(pageIndex).setSize(PAGESIZE) //数据的索引(从0开始)和查询条数
.setExplain(true).execute().actionGet();
// 遍历查询结果
if (rs != null && rs.getHits().getHits().length != 0) {
totalCount = (int) rs.getHits().getTotalHits(); //这一段可以获取结果的总数,对应的是分页类的总页数
SearchHit[] hits = rs.getHits().getHits(); //这个就是es查询出的结果,设置的是从索引开始查询10条
//List<SearchHit> page = page(currentPageNo, PAGESIZE, hits);
for (SearchHit hit : hits) {
Map<String, Object> source = hit.getSource(); //这个方法使查出的数据表现为map格式,同样也可以得到string类型的json数据
//针对id做出的查询
Map<String, Object> map = new HashMap(); //一下是根据es里面存放的id,向数据库查询name值用于展示
Long sspAdvertiserId = (Long) source.get("sspAdvertiserId");
if (sspAdvertiserId != null) {
String sspAdvertiserName = findSspAdvertiserName(sspAdvertiserId);
map.put("sspAdvertiserName", sspAdvertiserName);
}
Long sspOrderId = (Long) source.get("sspOrderId");
if (sspOrderId != null) {
String sspOrderName = findSspOrderName(sspOrderId);
map.put("sspOrderName", sspOrderName);
}
Long sspPlanId = (Long) source.get("sspPlanId");
if (sspPlanId != null) {
String sspPlanName = findSspPlanName(sspPlanId);
map.put("sspPlanName", sspPlanName);
}
Long sspCreativeId = (Long) source.get("sspCreativeId");
if (sspCreativeId != null) {
String sspCreativeName = findSspCreativeName(sspCreativeId);
map.put("sspCreativeName", sspCreativeName);
}
source.putAll(map);
list.add(source);
//System.out.println(hit.getSourceAsString());
}
}
return new Pagination<Map<String, Object>>(totalCount, PAGESIZE, currentPageNo, list.toArray(new Map[]{})); //分页处理类
}
private String findSspAdvertiserName(Long advertiserId) {
SspAdvertiser sspAdvertiser = new SspAdvertiser();
sspAdvertiser.setId(advertiserId);
RestResponse restResponse = sspAdvertiserService.find(sspAdvertiser);
ArrayList result = (ArrayList) restResponse.getResult();
LinkedHashMap map = (LinkedHashMap) result.get(0);
String name = (String) map.get("name");
return name;
}
private String findSspOrderName(Long orderId) {
String name = null;
try {
RestResponse restResponse = sspOrderService.find(orderId);
ArrayList result = (ArrayList) restResponse.getResult();
LinkedHashMap map = (LinkedHashMap) result.get(0);
name = (String) map.get("name");
} catch (Exception e) {
LOG.error("订单查询失败");
}
return name;
}
private String findSspPlanName(Long planId) {
String name = null;
try {
RestResponse restResponse = sspPlanService.find(planId);
LinkedHashMap map = (LinkedHashMap) restResponse.getResult();
name = (String) map.get("name");
} catch (Exception e) {
LOG.error("计划查询失败");
}
return name;
}
private String findSspCreativeName(Long creativeId) {
SspCreative creative = new SspCreative();
creative.setId(creativeId);
RestResponse restResponse = sspCreativeService.find(creative);
ArrayList result = (ArrayList) restResponse.getResult();
LinkedHashMap map = (LinkedHashMap) result.get(0);
String name = (String) map.get("creativeName");
return name;
}
/* public List<SearchHit> page(int pageNo, int pageSize, SearchHit[] hits) {
List<SearchHit> result = new ArrayList<>();
if (hits != null && hits.length > 0) {
int allCount = hits.length;
int pageCount = (allCount + pageSize - 1) / pageSize;
if (pageNo >= pageCount) {
pageNo = pageCount;
}
if (pageNo < 1) {
pageNo = 1;
}
int start = (pageNo - 1) * pageSize;
int end = pageNo * pageSize;
if (end >= allCount) {
end = allCount;
}
for (int i = start; i < end; i++) {
result.add(hits[i]);
}
}
return (result != null && result.size() > 0) ? result : null;
}*/
}
附:
查询类型
1、query and fetch
向索引的所有分片(shard)都发出查询请求,各分片返回的时候把元素文档(document)和计算后的排名信息一起返回。这种搜索方式是最快的。因为相比下面的几种搜索方式,这种查询方法只需要去shard查询一次。但是各个shard返回的结果的数量之和可能是用户要求的size的n倍。
2、query then fetch(默认的搜索方式)
如果你搜索时,没有指定搜索方式,就是使用的这种搜索方式。这种搜索方式,大概分两个步骤,第一步,先向所有的shard发出请求,各分片只返回排序和排名相关的信息(注意,不包括文档document),然后按照各分片返回的分数进行重新排序和排名,取前size个文档。然后进行第二步,去相关的shard取document。这种方式返回的document与用户要求的size是相等的。
3、DFS query and fetch
这种方式比第一种方式多了一个初始化散发(initial scatter)步骤,有这一步,据说可以更精确控制搜索打分和排名。
4、DFS query then fetch
比第2种方式多了一个初始化散发(initial scatter)步骤。