我们采用2.1版本,2.1版本和1.x版本在api上面有许多不同之处,从1.x版本升级上来的伙伴需要注意,api用法上面都能找到对应的使用。具体的api请参照
https://www.elastic.co/guide/en/elasticsearch/client/java-api/2.1/index.html
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>2.1.2</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>20.0</version>
</dependency>
建立服务器连接
这一步类似mysql数据库要获取一个DataSource
核心代码
public interface ElasticSearchSource {
public Client getClient();
}
import com.jd.poplog.dao.elasticsearch.ElasticSearchSource;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.client.Client;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.InetSocketTransportAddress;
import java.net.InetAddress;
import java.net.UnknownHostException;
public class ElasticSearchClientFactory implements ElasticSearchSource{
private String clusterName;
private Client client;
static public TransportClient tclient = null;
public Client getClient() {
return client;
}
/**
* 创建es client
* clusterName:集群名字
* nodeIp:集群中节点的ip地址
* nodePort:节点的端口
*
* @return
*/
public void init() throws ElasticsearchException {
synchronized (this){
Settings settings = Settings.settingsBuilder()
.put("cluster.name", clusterName).build();
//创建集群client并添加集群节点地址
tclient = TransportClient.builder().settings(settings).build();
try {
tclient.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("192.168.200.189"),9303))//以下是新增加节点
.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("192.168.200.190"),9303));
client = tclient;
} catch (UnknownHostException e) {
e.printStackTrace();
} finally {
}
}
}
public void close() {
if (null != client) {
client.close();
}
}
public void setClusterName(String clusterName) {
this.clusterName = clusterName;
}
}
索引数据
有三种方法,使用json字符串,使用map,使用业务bean,参考:
我们介绍使用bean的方法,也是平时开发中最常用的方法,这里包含索引时候的路由字段,当然查询的时候也要根据这个路由字段
public <T> boolean indexWithBean(T t,String routingId) throws ESException {
try{
//用javabean构建json对象
ObjectMapper mapper = new ObjectMapper();
byte[] json = mapper.writeValueAsBytes(t);
//指定索引名称,type名称和documentId(documentId可选,不设置则系统自动生成)创建document
IndexResponse response = elasticSearchSource.getClient().prepareIndex(indexName, indexType)
.setSource(json)
.setRouting(routingId)
.execute()
.actionGet();
boolean created = response.isCreated();
return created;
}catch (Exception e){
_logger.error("indexWithBean is err.",e);
throw new ESException("insert into es exception",e);
}
}
查询数据
查询稍微复杂一些,涉及分页,高亮,分词等动作,我们一一来描述
分页相关类:
import java.util.List;
public interface PaginatedList<T> extends List<T> {
boolean isMiddlePage();
boolean isLastPage();
boolean isNextPageAvailable();
boolean isPreviousPageAvailable();
int getPageSize();
void setPageSize(int var1);
int getIndex();
void setIndex(int var1);
int getTotalItem();
void setTotalItem(int var1);
int getTotalPage();
int getStartRow();
int getEndRow();
int getNextPage();
int getPreviousPage();
boolean isFirstPage();
}
import java.util.ArrayList;
public class Page<T> extends ArrayList<T> implements PaginatedList<T> {
/**
* 默认每页的记录数量
*/
public static final int PAGESIZE_DEFAULT = 20;
/**
* 每页大小
*/
private int pageSize;
/**
* 当前页。第一页是1
*/
private int index;
/**
* 总记录数
*/
private int totalItem;
/**
* 总页数
*/
private int totalPage;
/**
* 分页后的记录开始的地方
* 第一条记录是1
*/
private int startRow;
/**
* 分页后的记录结束的地方
*/
private int endRow;
/**
* 默认构造方法
*/
public Page() {
repaginate();
}
/**
* 带当前页和页大小的构造方法
*
* @param index 当前页
* @param pageSize 页大小
*/
public Page(int index, int pageSize) {
this.index = index;
this.pageSize = pageSize;
repaginate();
}
/**
* 表示是不是第一页
*
* @return true 是; false 不是
*/
public boolean isFirstPage() {
return index <= 1;
}
public boolean isMiddlePage() {
return !(isFirstPage() || isLastPage());
}
public boolean isLastPage() {
return index >= totalPage;
}
public boolean isNextPageAvailable() {
return !isLastPage();
}
public boolean isPreviousPageAvailable() {
return !isFirstPage();
}
/**
* 下一页号
*
* @return 取得下一页号
*/
public int getNextPage() {
if (isLastPage()) {
return totalItem;
} else {
return index + 1;
}
}
public int getPreviousPage() {
if (isFirstPage()) {
return 1;
} else {
return index - 1;
}
}
/**
* Method getPageSize returns the pageSize of this PaginatedArrayList object.
* <p/>
* 每页大小
*
* @return the pageSize (type int) of this PaginatedArrayList object.
*/
public int getPageSize() {
return pageSize;
}
/**
* Method setPageSize sets the pageSize of this PaginatedArrayList object.
* <p/>
* 每页大小
*
* @param pageSize the pageSize of this PaginatedArrayList object.
*/
public void setPageSize(int pageSize) {
this.pageSize = pageSize;
repaginate();
}
/**
* Method getIndex returns the index of this PaginatedArrayList object.
* <p/>
* 当前页。第一页是1
*
* @return the index (type int) of this PaginatedArrayList object.
*/
public int getIndex() {
return index;
}
/**
* Method setIndex sets the index of this PaginatedArrayList object.
* <p/>
* 当前页。第一页是1
*
* @param index the index of this PaginatedArrayList object.
*/
public void setIndex(int index) {
this.index = index;
repaginate();
}
/**
* Method getTotalItem returns the totalItem of this PaginatedArrayList object.
* <p/>
* 总记录数
*
* @return the totalItem (type int) of this PaginatedArrayList object.
*/
public int getTotalItem() {
return totalItem;
}
/**
* Method setTotalItem sets the totalItem of this PaginatedArrayList object.
* <p/>
* 总记录数
*
* @param totalItem the totalItem of this PaginatedArrayList object.
*/
public void setTotalItem(int totalItem) {
this.totalItem = totalItem;
repaginate();
}
/**
* Method getTotalPage returns the totalPage of this PaginatedArrayList object.
* <p/>
* 总页数
*
* @return the totalPage (type int) of this PaginatedArrayList object.
*/
public int getTotalPage() {
return totalPage;
}
/**
* Method getStartRow returns the startRow of this PaginatedArrayList object.
* <p/>
* 分页后的记录开始的地方
*
* @return the startRow (type int) of this PaginatedArrayList object.
*/
public int getStartRow() {
return startRow;
}
/**
* Method getEndRow returns the endRow of this PaginatedArrayList object.
* <p/>
* 分页后的记录结束的地方
*
* @return the endRow (type int) of this PaginatedArrayList object.
*/
public int getEndRow() {
return endRow;
}
/**
* Method repaginate ...
*/
private void repaginate() {
if (pageSize < 1) { //防止程序偷懒,list和分页的混合使用
pageSize = PAGESIZE_DEFAULT;
}
if (index < 1) {
index = 1;//恢复到第一页
}
if (totalItem > 0) {
totalPage = totalItem / pageSize + (totalItem % pageSize > 0 ? 1 : 0);
if (index > totalPage) {
index = totalPage; //最大页
}
endRow = index * pageSize;
//起始startRow应为0
startRow = endRow - pageSize;
if (endRow > totalItem) {
endRow = totalItem;
}
}
}
}
elasticsearch相关
public <T> List<T> getByQueryBean(OpLogQuery opLogQuery,PaginatedList page,String sortField,GetMapping<T> get) {
List<T> logs = new ArrayList<T>();
try{
int startRow= (page.getIndex()-1)*page.getPageSize();
BoolQueryBuilder builder = buildBoolQuery(opLogQuery);
QueryBuilder range = QueryBuilders.rangeQuery("opTime").gte(startTime).lt(endTime));
builder.must(range);
SearchResponse sResponse = elasticSearchSource.getClient().prepareSearch(indexName1,indexName2,...)//这里可以跨多个索引查询,比如每天一个索引的时候,es的这种api非常方便
.setTypes(esType)
.setSearchType(SearchType.QUERY_THEN_FETCH)
.setQuery(builder)
//设置排序field
.addSort(sortField, SortOrder.DESC)
//设置高亮field
.addHighlightedField("opContent")
//设置分页
.setFrom(startRow).setSize(page.getPageSize())
.execute()
.actionGet();
SearchHits hits = sResponse.getHits();
int count = (int) hits.getTotalHits();
page.setTotalItem(count);
SearchHit[] hitArray = hits.getHits();
for (int i = 0; i < hitArray.length; i++) {
SearchHit hit = hitArray[i];
logs.add(get.mapping(hit));
}
}catch (Exception e){
throw new ESException("query es EXCPTION",e);
}
return logs;
}
//通过这个方法可以把查询条件组装到BoolQueryBuilder 中
private BoolQueryBuilder buildBoolQuery(OpLogQuery opLogQuery) {
Map<String,String> map = new HashMap<String, String>();
map.put("bizType",opLogQuery.getBusinessType());
map.put("opObject",opLogQuery.getOperateObj());
BoolQueryBuilder boolQuery = new BoolQueryBuilder();
for (Map.Entry<String, String> entry : map.entrySet()){
if (StringUtils.isNotBlank(entry.getValue())&&!DEFAULT_VALUE.equals(entry.getValue())){
// boolQuery.must(QueryBuilders.matchQuery(entry.getKey(), entry.getValue()));
boolQuery.must(QueryBuilders.prefixQuery(entry.getKey(), entry.getValue()));
}
}
return boolQuery;
}
关于GetMapping
import org.elasticsearch.search.SearchHit;
public interface GetMapping<T> {
T mapping(SearchHit hit);
}
调用
elasticSearchDao.getByQueryBean(opLogQuery, page, "opTime", new GetMapping<OpLog>() {
@Override
public OpLog mapping(SearchHit hit) {
OpLog opLog = new OpLog();
Map<String, Object> fields = hit.getSource();
opLog.setVenderId(fields.get("venderId").toString());
opLog.setOpUser(fields.get("opUser").toString());
opLog.setOpTime(fields.get("opTime").toString());
//设置高亮
Map<String, HighlightField> result = hit.getHighlightFields();
if(result.size()>0){
HighlightField opContentField = result.get("opContent");
Text[] opContentTexts = opContentField.getFragments();
for(Text text : opContentTexts){
opLog.setOpValue(text.string());
}
}
return opLog;
}
});
到此,Elasticsearch的基本插入和查询就介绍完毕。
参考资料:https://www.elastic.co/guide/en/elasticsearch/client/java-api/2.1/java-docs-index.html