编写不易,转载请注明(http://shihlei.iteye.com/blog/2411470)!
一 概述
Jest 是一个Java 版的ElasticSearch Http Rest 客户端,基于HttpClient 封装实现。
个人感觉好处:
1 连接池可控
2 简单封装了Bean 到Document 的Mapping过程
github:https://github.com/searchbox-io/Jest/tree/master/jest
二 环境
(1)版本信息
elasticsearch:elasticsearch-6.2.2.tar.gz
jest:5.3.3
(2)环境准备:
a)创建索引
curl -H 'Content-Type: application/json' -XPUT 'http://localhost:9200/indexdb' -d '{ "settings" : { "index" : { "number_of_shards" : 1, "number_of_replicas" : 1 } } }'
b)创建mapping
curl -H 'Content-Type: application/json' -XPUT 'http://localhost:9200/indexdb/_mapping/docs' -d '{
"properties": {
"id": {
"type": "long",
"index": "false"
},
"title": {
"type": "keyword",
},
"author": {
"type": "keyword",
},
"tags": {
"type": "keyword",
"boost" : 3.0,
},
"publishTime": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss"
}
}
}'
注:升级到6.2 mapping 取消string 类型,index 只接受true,false。
三 Demo
1)maven 依赖
<!--Java HTTP Rest client for ElasticSearch.-->
<dependency>
<groupId>io.searchbox</groupId>
<artifactId>jest</artifactId>
<version>5.3.3</version>
</dependency>
2)Bean
package x.search.es.simple.bean;
import java.util.Arrays;
import java.util.Date;
import io.searchbox.annotations.JestId;
public class Document implements Cloneable {
@JestId
private long id;
private String title;
private String author;
private String[] tags;
private Date publishTime;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String[] getTags() {
return tags;
}
public void setTags(String[] tags) {
this.tags = tags;
}
public Date getPublishTime() {
return publishTime;
}
public void setPublishTime(Date publishTime) {
this.publishTime = publishTime;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
@Override
public String toString() {
return "Document{" +
"id=" + id +
", title='" + title + '\'' +
", author='" + author + '\'' +
", tags=" + Arrays.toString(tags) +
", publishTime=" + publishTime +
'}';
}
}
3)JestClient 工厂
package x.search.es.simple.jest;
import java.util.Objects;
import com.google.gson.GsonBuilder;
import io.searchbox.client.JestClient;
import io.searchbox.client.JestClientFactory;
import io.searchbox.client.config.HttpClientConfig;
public class EsJestClient {
private static final String ES_HOST = "http://127.0.0.1";
private static final int ES_HTTP_PORT = 9200;
private static JestClient client;
/**
* 获取客户端
*
* @return jestclient
*/
public static synchronized JestClient getClient() {
if (client == null) {
build();
}
return client;
}
/**
* 关闭客户端
*/
public static void close(JestClient client) {
if (!Objects.isNull(client)) {
try {
client.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 建立连接
*/
private static void build() {
JestClientFactory factory = new JestClientFactory();
factory.setHttpClientConfig(
new HttpClientConfig
.Builder(ES_HOST + ":" + ES_HTTP_PORT)
.multiThreaded(true)
//一个route 默认不超过2个连接 路由是指连接到某个远程注解的个数。总连接数=route个数 * defaultMaxTotalConnectionPerRoute
.defaultMaxTotalConnectionPerRoute(2)
//所有route连接总数
.maxTotalConnection(2)
.connTimeout(10000)
.readTimeout(10000)
.gson(new GsonBuilder()
.setDateFormat("yyyy-MM-dd HH:mm:ss")
.create())
.build()
);
client = factory.getObject();
}
}
4)CRUD
(a)IDocumentDao
package x.search.es.simple;
import x.search.es.simple.bean.Document;
import java.util.List;
public interface IDocumentDao {
/**
* 插入
*
* @param doc
* @return
*/
boolean insert(Document doc);
/**
* 替换
*
* @param doc
* @return
*/
boolean replace(Document doc);
/**
* 更新
*
* @param doc
* @return
*/
boolean update(Document doc);
/**
* 删除
*
* @param id
* @return
*/
boolean delete(long id);
/**
* 根据ID查询
*
* @param id
* @return
*/
Document searchById(long id);
/**
* 条件查询
*
* @param criterias
* @return
*/
List<Document> search(List<Criteria> criterias);
/**
* 条件删除
*
* @param criterias
* @return 删除的document数量
*/
int deleteByQuery(List<Criteria> criterias);
}
(b)Criteria
package x.search.es.simple;
public class Criteria {
private String fieldName;
private Object fieldValue;
public Criteria(String fieldName, Object fieldValue) {
this.fieldName = fieldName;
this.fieldValue = fieldValue;
}
public String getFieldName() {
return fieldName;
}
public Object getFieldValue() {
return fieldValue;
}
}
(c)DocumentDB
package x.search.es.simple;
public class DocumentDB {
//indices 名必须小写
public static final String INDICES = "indexdb";
// type 名必须小写
public static final String TYPE = "docs";
}
(d)DocumentJestDaoImpl
package x.search.es.simple.jest;
import java.util.Date;
import java.util.List;
import io.searchbox.client.JestClient;
import io.searchbox.client.JestResult;
import io.searchbox.core.Delete;
import io.searchbox.core.DeleteByQuery;
import io.searchbox.core.DocumentResult;
import io.searchbox.core.Get;
import io.searchbox.core.Index;
import io.searchbox.core.Search;
import io.searchbox.core.SearchResult;
import io.searchbox.core.Update;
import io.searchbox.core.UpdateByQuery;
import io.searchbox.core.UpdateByQueryResult;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import x.search.es.simple.Criteria;
import x.search.es.simple.DocumentDB;
import x.search.es.simple.IDocumentDao;
import x.search.es.simple.bean.Document;
public class DocumentJestDaoImpl implements IDocumentDao {
private JestClient client;
private DocumentJestDaoImpl(JestClient client) {
this.client = client;
}
public static void main(String[] args) {
JestClient client = EsJestClient.getClient();
DocumentJestDaoImpl documentDao = new DocumentJestDaoImpl(client);
Document document = new Document();
document.setId(1);
document.setTitle("foo");
document.setAuthor("bar");
document.setPublishTime(new Date());
document.setTags(new String[]{"tag1", "tag2", "tag3", "tag4"});
//保存
documentDao.insert(document);
System.out.println(documentDao.searchById(1));
}
/**
* 插入
*
* @param doc 文档
* @return 是佛插入成功
*/
@Override
public boolean insert(Document doc) {
try {
DocumentResult result = client.execute(new Index.Builder(doc)
.index(DocumentDB.INDICES)
.type(DocumentDB.TYPE)
.refresh(true)
.build());
return result.isSucceeded();
} catch (Exception e) {
throw new RuntimeException("insert exception", e);
}
}
/**
* 替换
*
* @param doc 文档
* @return 是否执行成功
*/
@Override
public boolean replace(Document doc) {
return update(doc);
}
/**
* 更新
*
* @param doc 文档
* @return 是否更新成功
*/
@Override
public boolean update(Document doc) {
try {
DocumentResult result = client.execute(new Update.Builder(doc)
.index(DocumentDB.INDICES)
.type(DocumentDB.TYPE)
.refresh(true)
.build());
return result.isSucceeded();
} catch (Exception e) {
throw new RuntimeException("update exception", e);
}
}
/**
* 删除
*
* @param id 文档id
* @return 是否执行成功
*/
@Override
public boolean delete(long id) {
try {
DocumentResult result = client.execute(new Delete.Builder(String.valueOf(id))
.index(DocumentDB.INDICES)
.type(DocumentDB.TYPE)
.build());
return result.isSucceeded();
} catch (Exception e) {
throw new RuntimeException("delete exception", e);
}
}
/**
* 根据ID查询
*
* @param id id
* @return 文档
*/
@Override
public Document searchById(long id) {
try {
DocumentResult result = client.execute(new Get.Builder(DocumentDB.INDICES, String.valueOf(id))
.type(DocumentDB.TYPE)
.build());
return result.getSourceAsObject(Document.class);
} catch (Exception e) {
throw new RuntimeException("searchById exception", e);
}
}
/**
* 条件查询
*
* @param criterias 条件列表
* @return 结果集
*/
@Override
public List<Document> search(List<Criteria> criterias) {
try {
SearchResult result = client.execute(new Search.Builder(buildSearch(criterias).toString())
// multiple index or types can be added.
.addIndex(DocumentDB.INDICES)
.addType(DocumentDB.TYPE)
.build());
return result.getSourceAsObjectList(Document.class, false);
} catch (Exception e) {
throw new RuntimeException("search exception", e);
}
}
private SearchSourceBuilder buildSearch(List<Criteria> criterias) {
//指定查询的库表
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
if (criterias != null && !criterias.isEmpty()) {
//构建查询条件必须嵌入filter中!
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
for (Criteria c : criterias) {
boolQueryBuilder.filter(QueryBuilders.termQuery(c.getFieldName(), c.getFieldValue()));
}
searchSourceBuilder.query(boolQueryBuilder);
}
return searchSourceBuilder;
}
/**
* 条件删除 ,ElasticSearch V5.1 以上可用
*
* @param criterias 条件
* @return 删除的document数量
*/
@Override
public int deleteByQuery(List<Criteria> criterias) {
try {
JestResult result = client.execute(new DeleteByQuery.Builder(buildSearch(criterias).toString())
.addIndex(DocumentDB.INDICES)
.addType(DocumentDB.TYPE)
.build());
return result.getJsonObject().get("deleted").getAsInt();
} catch (Exception e) {
throw new RuntimeException("deleteByQuery exception", e);
}
}
}
附录:
1)elasticsearch 6.2 安装
(1)下载解压
cd /opt/ curl -L -O https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.2.2.tar.gz tar -xvf elasticsearch-6.2.2.tar.gz
(2)创建用户
groupadd es useradd -r -g es -s /bin/bash es chown -hR es:es /opt/elasticsearch-6.2.2
(3)启动
su es
cd /opt/elasticsearch-6.2.2/bin
./elasticsearch