TransportClient使用总结
优点:使用Transport 接口进行通信,能够使用ES集群中的一些特性,性能最好。缺点:JAR包版本需与ES集群版本一致,ES集群升级,客户端也跟着升级到相同版本。ES 7.0 之后要逐步去掉。
优缺点
优点:
使用Transport 接口进行通信,能够使用ES集群中的一些特性,性能最好。
缺点:
JAR包版本需与ES集群版本一致,ES集群升级,客户端也跟着升级到相同版本。
ES 7.0 之后要逐步去掉。
使用准备
maven依赖
<!-- ES --> <dependency> <groupId>org.elasticsearch.client</groupId> <artifactId>transport</artifactId> <version>5.6.4</version> </dependency> <dependency> <groupId>org.elasticsearch</groupId> <artifactId>elasticsearch</artifactId> <version>5.6.4</version> </dependency><!-- log4j --> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>2.17.0</version> </dependency>
config.proerties
#es
es_ip=x.x.10.183
es_port=9300
es_cluster_name=my-application
初始化
import com.jfinal.kit.Prop;
import com.jfinal.kit.PropKit;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.InetSocketTransportAddress;
import org.elasticsearch.transport.client.PreBuiltTransportClient;
import java.io.File;
import java.net.InetAddress;
import java.net.UnknownHostException;
public enum EsClientEnum {
INSTANCE;
private TransportClient client;
private EsClientEnum(){
Prop prop = PropKit.use(new File("./conf/config.properties"),"gbk");
String es_cluster_name = prop.get("es_cluster_name");
String es_ip = prop.get("es_ip");
Integer es_port = prop.getInt("es_port");
System.out.println("es_cluster_name = " + es_cluster_name);
//设置集群名称
try {
Settings settings = Settings.builder()
.put("cluster.name", es_cluster_name)
.put("client.transport.sniff", false) //启动嗅探功能,自动嗅探整个集群的状态,把集群中其他ES节点的ip添加到本地的客户端列表中
// .put("client.transport.ignore_cluster_name", true)//忽略集群名字验证, 打开后集群名字不对也能连接上
// .put("client.transport.nodes_sampler_interval", 5)//报错
// .put("client.transport.ping_timeout", 5) //报错, ping等待时间
.build();// 集群名
//创建client
client= new PreBuiltTransportClient(settings)
.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName(es_ip), es_port));
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
public TransportClient getClient() {
return client;
}
}
crud使用封装
import org.apache.log4j.Logger;
import org.elasticsearch.action.bulk.BulkRequestBuilder;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class ElasticSearchUtil {
private static final Logger logger = Logger.getLogger(ElasticSearchUtil.class);
private static TransportClient client =EsClientEnum.INSTANCE.getClient();
/**
* 通过prepareIndex增加文档,参数为json字符串
* @param index 索引名
* @param type 类型
* @param _id 数据id
* @param json 数据
*/
@SuppressWarnings("deprecation")
public static void insertData(String index, String type, String _id, String json) {
IndexResponse indexResponse = client.prepareIndex(index, type).setId(_id)
.setSource(json)
.get();
System.out.println(indexResponse.getVersion());
logger.info("数据插入ES成功!");
}
/**
* 功能描述:更新数据
* @param index 索引名
* @param type 类型
* @param _id 数据id
* @param json 数据
*/
@SuppressWarnings("deprecation")
public static void updateData(String index, String type, String _id, String json){
try {
UpdateRequest updateRequest = new UpdateRequest(index, type, _id).doc(json);
// client.prepareUpdate(index, type, _id).setDoc(json).get();
client.update(updateRequest).get();
} catch (Exception e) {
logger.error("update data failed." + e.getMessage());
}
}
/**
* 功能描述:删除指定数据
* @param index 索引名
* @param type 类型
* @param _id 数据id
*/
public static void deleteData(String index, String type, String _id) {
try {
DeleteResponse response = client.prepareDelete(index, type, _id).get();
System.out.println(response.isFragment());
logger.info("删除指定数据成功!");
} catch (Exception e) {
logger.error("删除指定数据失败!" + e);
}
}
/**
* 功能描述:批量插入数据
* @param index 索引名
* @param type 类型
* @param jsonList 批量数据
*/
@SuppressWarnings("deprecation")
public void bulkInsertData(String index, String type, List<String> jsonList) {
BulkRequestBuilder bulkRequest = client.prepareBulk();
jsonList.forEach(item -> {
bulkRequest.add(client.prepareIndex(index, type).setSource(item));
});
BulkResponse bulkResponse = bulkRequest.get();
if(!bulkResponse.hasFailures()) {
System.out.println(bulkResponse.getItems().length + "条数据插入完成!");
}
}
/**
* 执行查询
*
* @param query 查询器
* @return 当前查询对象
*/
private static List<Map<String, Object>> executeQuery(QueryBuilder query, String indexName,int from , int size) {
//搜索结果存入SearchResponse
SearchResponse response = client.prepareSearch(indexName)
.setQuery(query) //设置查询器
.setFrom(from) //开始位置
.setSize(size) //一次查询文档数
.get();
SearchHits hits = response.getHits();
if (response.getHits() == null) {
return null;
}
List<Map<String, Object>> resultList = new ArrayList<>();
for (SearchHit hit : hits) {
resultList.add(hit.getSourceAsMap());
}
return resultList;
}
/**
* 功能描述:关闭链接
*/
private static void close() {
client.close();
}
}
QueryBuilders
精确查询
精确,指的是查询关键字(或者关键字分词后),必须与目标分词结果完全匹配。
1.指定字符串作为关键词查询,关键词支持分词
//查询title字段中,包含 ”开发”、“开放" 这个字符串的document;相当于把"浦东开发开放"分词了,再查询;
QueryBuilders.queryStringQuery("开发开放").defaultField("title");
//不指定feild,查询范围为所有feild
QueryBuilders.queryStringQuery("青春");
//指定多个feild
QueryBuilders.queryStringQuery("青春").field("title").field("content");
2.以关键字“开发开放”,关键字不支持分词
QueryBuilders.termQuery("title", "开发开放")
QueryBuilders.termsQuery("fieldName", "fieldlValue1","fieldlValue2...")
3.以关键字“开发开放”,关键字支持分词
QueryBuilders.matchQuery("title", "开发开放")
QueryBuilders.multiMatchQuery("fieldlValue", "fieldName1", "fieldName2", "fieldName3")
模糊查询
模糊,是指查询关键字与目标关键字可以模糊匹配。
1.左右模糊查询,其中fuzziness的参数作用是在查询时,es动态的将查询关键词前后增加或者删除一个词,然后进行匹配
QueryBuilders.fuzzyQuery("title", "开发开放").fuzziness(Fuzziness.ONE)
2.前缀查询,查询title中以“开发开放”为前缀的document;
QueryBuilders.prefixQuery("title", "开发开放")
3.通配符查询,支持*和?,?表示单个字符;注意不建议将通配符作为前缀,否则导致查询很慢
QueryBuilders.wildcardQuery("title", "开*放")
QueryBuilders.wildcardQuery("title", "开?放")
注意
在分词的情况下,针对fuzzyQuery、prefixQuery、wildcardQuery不支持分词查询,即使有这种doucment数据,也不一定能查出来。
范围查询
QueryBuilders.rangeQuery("fieldName").from("fieldValue1").to("fieldValue2");
//开区间查询,默认是true,也就是包含
QueryBuilders.rangeQuery("fieldName").from("fieldValue1").to("fieldValue2").includeUpper(false).includeLower(false);
//大于
QueryBuilders.rangeQuery("fieldName").gt("fieldValue");
//大于等于
QueryBuilders.rangeQuery("fieldName").gte("fieldValue");
//小于
QueryBuilders.rangeQuery("fieldName").lt("fieldValue");
//小于等于
QueryBuilders.rangeQuery("fieldName").lte("fieldValue");
布尔查询
QueryBuilders.boolQuery()
QueryBuilders.boolQuery().must();//文档必须完全匹配条件,相当于and
QueryBuilders.boolQuery().mustNot();//文档必须不匹配条件,相当于not
QueryBuilders.boolQuery().should();//至少满足一个条件,这个文档就符合should,相当于or
短语查询
PhraseQuery
由于精准/精确查询要求太严格,而关键词查询只是取决于包含与否,并不对term之间的位置有所要求,但是 对于 短语来说是有位置要求的,如 hello world这一短语,当进行 关键词搜索keywords = world hello,也会返回出来因为 关键词查询只进行包含判断,并不进行位置判断,那么在这种情况下 短语查询应运而生。
QueryBuilders.matchPhraseQuery("title","hello world");
PhrasePrefixQuery
PhrasePrefixQuery和PhraseQuery的区别
摘自ES官网:The match_phrase_prefix is the same as match_phrase, except that it allows for prefix matches on the last term in the text.
当搜索项为中文时,几乎无差别,当搜索英文时存在较大差异,比如quick brown fox,
当搜索 quick brown f时 addPhraseQuery不会返回结果,当进行addPhrasePrefixQuery 时会返回结果,因为会对最后一个 term 的前缀进行匹配;
QueryBuilders.matchPhrasePrefixQuery("title","hello world");
SearchResponse
EsPageUtil封装
额外依赖
<dependency>
<groupId>com.github.miemiedev</groupId>
<artifactId>mybatis-paginator</artifactId>
<version>1.2.17</version>
</dependency>
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import page.PageBounds;
import page.PageList;
import page.Paginator;
import java.util.ArrayList;
import java.util.List;
/**
* @Description: Es 查询公用方法类
* @Date:Created in 2018/11/12 0012
*/
public class EsPageUtil<E> {
private Logger logger = LoggerFactory.getLogger(this.getClass());
private Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create();
/**
* 设置ES分页查询
*
* @param pageBounds 分页对象
* @param sourceBuilder 查询条件
*/
public static void setPageByPageBounds(PageBounds pageBounds, SearchSourceBuilder sourceBuilder) {
int begin = (pageBounds.getPage() - 1) * pageBounds.getLimit();
int end = begin + pageBounds.getLimit();
//设置from确定结果索引的选项以开始搜索。默认为0。
sourceBuilder.from(begin);
//设置size确定要返回的搜索命中数的选项。默认为10。
sourceBuilder.size(end);
}
/**
* 返回分页对象
*
* @param pageBounds 分页对象
* @param response Es 查询结果
* @param clazz clazz对象
* @return page list
*/
public PageList<E> getPageList(PageBounds pageBounds, SearchResponse response, Class<E> clazz) {
logger.debug("es 查询结果:{}", response.toString());
List<E> list = new ArrayList<>();
SearchHit[] hits = response.getHits().getHits();
for (SearchHit hit : hits) {
E e = gson.fromJson(gson.toJson(hit.getSource()), clazz);
list.add(e);
}
Paginator paginator = new Paginator(pageBounds.getPage(), pageBounds.getLimit(), (int) response.getHits().getTotalHits());
return new PageList<>(list, paginator);
}
/**
* @Description: 返回查询列表
* @param response
* @param clazz
* @return List<E>
* @throws
*/
public List<E> getList(SearchResponse response, Class<E> clazz) {
logger.debug("es 查询结果:{}", response.toString());
List<E> list = new ArrayList<>();
SearchHit[] hits = response.getHits().getHits();
for (SearchHit hit : hits) {
E e = gson.fromJson(gson.toJson(hit.getSource()), clazz);
list.add(e);
}
return list;
}
}
EsPageUtil使用
@Test
public void pageTest(){
int page=3;
int pageSize=2;
PageBounds pageBounds=new PageBounds(page,pageSize);
EsPageUtil<Article> esUtil=new EsPageUtil<Article>();
BoolQueryBuilder boolQueryBuilder= QueryBuilders.boolQuery();
boolQueryBuilder.must(QueryBuilders.matchAllQuery());
SearchResponse response= EsClientEnum.INSTANCE.getClient().prepareSearch("article").setTypes("article")
.setQuery(boolQueryBuilder)
.addSort("id", SortOrder.ASC)
// .setFrom((page-1)*pageSize).setSize(pageSize)
.setFrom(pageBounds.getOffset()).setSize(pageBounds.getLimit())
.setExplain(true)
.get();
PageList<Article> pageList = esUtil.getPageList(pageBounds, response, Article.class);
Paginator paginator = pageList.getPaginator(); //可以获得page limit totalCount
System.out.println("---------------------------");
}
结果高亮
import com.wg.utils.EsClientEnum;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortOrder;
import org.junit.Test;
import java.util.Map;
public class HighLightTest {
@Test
public void testHigh(){
HighlightBuilder highlightBuilder = getHighlightBuilder("title");
SearchResponse searchResponse = EsClientEnum.INSTANCE.getClient().prepareSearch("article").setTypes("article")
.setQuery(QueryBuilders.matchQuery("title", "title"))
.addSort("id", SortOrder.ASC)
.highlighter(highlightBuilder)
.get();
SearchHits hits = searchResponse.getHits();
for (SearchHit hit : hits) {
String title = replaceAttr(hit, "title");
System.out.println("title = " + title);
}
}
private HighlightBuilder getHighlightBuilder(String field){
//配置标题高亮显示
HighlightBuilder highlightBuilder = new HighlightBuilder(); //生成高亮查询器
highlightBuilder.field(field); //高亮查询字段
// highlightBuilder.field(content); //高亮查询字段
highlightBuilder.requireFieldMatch(false); //如果要多个字段高亮,这项要为false
highlightBuilder.preTags("<span style=\"color:red\">"); //高亮设置
highlightBuilder.postTags("</span>");
//下面这两项,如果你要高亮如文字内容等有很多字的字段,必须配置,不然会导致高亮不全,文章内容缺失等
highlightBuilder.fragmentSize(800000); //最大高亮分片数
highlightBuilder.numOfFragments(0); //从第一个分片获取高亮片段
return highlightBuilder;
}
/**
* 替换高亮属性
*
* @param searchHit 查询结果
* @return
*/
private String replaceAttr(SearchHit searchHit, String attr) {
Map<String, HighlightField> highlightFields = searchHit.getHighlightFields();
HighlightField hField = highlightFields.get(attr);
if (hField != null) {
//替换高亮字段
Text[] fragments = hField.fragments();
StringBuilder text = new StringBuilder();
for (Text textGet : fragments) {
text.append(textGet);
}
return text.toString();
}
return null;
}
}
深度分页scroll
/**
* 使用Scroll方法分页
*/
@Test
public void queryPageScroll(){
QueryBuilder qb = QueryBuilders.matchAllQuery();
TransportClient client = EsClientEnum.INSTANCE.getClient();
SearchResponse scrollResp = client.prepareSearch("article")
// .addSort(FieldSortBuilder.DOC_FIELD_NAME, SortOrder.ASC)
.addSort("id", SortOrder.ASC)
.setScroll(new TimeValue(60000))
.setQuery(qb)
.setSize(1).get();
do {
for (SearchHit hit : scrollResp.getHits().getHits()) {
println(hit);
}
scrollResp = client.prepareSearchScroll(scrollResp.getScrollId()).setScroll(new TimeValue(60000)).execute().actionGet();
} while(scrollResp.getHits().getHits().length != 0);
}
/**
* 输出结果SearchResponse
* @param
*/
public static void println(SearchHit searchHit){
System.err.println("*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-");
System.err.println(
"docId : " + searchHit.docId() + "\n" +
"getId : " + searchHit.getId() + "\n" +
"getIndex : " + searchHit.getIndex()+ "\n" +
"getScore : " + searchHit.getScore() + "\n" +
"getSourceAsString : " + searchHit.getSourceAsString() + "\n" +
"getType : " + searchHit.getType() + "\n" +
"getVersion : " + searchHit.getVersion() + "\n" +
"fieldsOrNull : " + searchHit.fieldsOrNull() + "\n" +
"getExplanation : " + searchHit.getExplanation() + "\n" +
"getFields : " + searchHit.getFields() + "\n" +
"highlightFields : " + searchHit.highlightFields() + "\n" +
"hasSource : " + searchHit.hasSource()
);
}
aggregation
多重聚合封装
import com.wg.utils.EsClientEnum;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.aggregations.metrics.avg.InternalAvg;
import org.elasticsearch.search.aggregations.metrics.cardinality.InternalCardinality;
import org.elasticsearch.search.aggregations.metrics.max.InternalMax;
import org.elasticsearch.search.aggregations.metrics.min.InternalMin;
import org.elasticsearch.search.aggregations.metrics.sum.Sum;
import org.elasticsearch.search.aggregations.metrics.valuecount.InternalValueCount;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
public class AggUtil {
private ArrayList<Object> results(SearchResponse agg){
Map<String, Aggregation> aggregations = agg.getAggregations().asMap();
ArrayList<Object> objects = new ArrayList<>();
for (Map.Entry<String, Aggregation> entry:aggregations.entrySet()
) {
String key = entry.getKey();
Aggregation value = entry.getValue();
HashMap<String, Object> group = new HashMap<>();
parseAggs(value,group,key,objects);
}
return objects;
}
//解析聚合结果
private ArrayList<Object> parseAggs(Aggregation agg, HashMap<String, Object> group,String field,ArrayList<Object> objects){
if (agg instanceof Terms){
for (Terms.Bucket bucket:((Terms) agg).getBuckets() ){
String keyAsString = bucket.getKeyAsString();
group.put(field,keyAsString);
for (Map.Entry<String, Aggregation> entry :bucket.getAggregations().asMap().entrySet()
) {
String key = entry.getKey();
Aggregation value = entry.getValue();
if (value instanceof Terms){
parseAggs(value,group,key,objects);
}else {
LinkedHashMap<String, Object> map = package2map(bucket);
map.putAll(group);
objects.add(map);
break;
}
}
}
}
return objects;
}
private LinkedHashMap<String, Object> package2map(Terms.Bucket bucket){
LinkedHashMap<String, Object> map = new LinkedHashMap<>();
for (Map.Entry<String, Aggregation> entry :bucket.getAggregations().asMap().entrySet()
) {
String key = entry.getKey();
Aggregation value = entry.getValue();
map.put(key,getvalue(value));
}
return map;
}
//取值
public String getvalue(Aggregation agg){
String type = agg.getType();
String result="";
switch (type){
case "avg":
result=String.valueOf(((InternalAvg) agg).getValue());
break;
case "sum":
result=String.valueOf(((Sum) agg).getValue());
break;
case "value_count":
result=String.valueOf(((InternalValueCount) agg).getValue());
break;
case "min":
result=String.valueOf(((InternalMin) agg).getValue());
break;
case "max":
result=String.valueOf(((InternalMax) agg).getValue());
break;
case "cardinality":
result=String.valueOf(((InternalCardinality) agg).getValue());
break;
default:
result=String.valueOf(agg);
break;
}
return result;
}
private void getAggsResult(TransportClient client){
SearchResponse agg = client.prepareSearch("hisms_sz")
.setTypes("cz")
.addAggregation(
AggregationBuilders.terms("id_mdc").field("id_mdc").size(26)//设置聚合条件 group by id_mdc,id_drg
.subAggregation(
AggregationBuilders.terms("name_drg").field("name_drg").size(700)
.subAggregation(AggregationBuilders.avg("avg").field("yka055"))// 聚合结果 avg(date
.subAggregation(AggregationBuilders.sum("sum").field("yka055"))
.subAggregation(AggregationBuilders.min("min").field("yka055"))
.subAggregation(AggregationBuilders.count("count").field("aac003"))
.subAggregation(AggregationBuilders.cardinality("cardinality").field("aac003"))
)
)
.execute().actionGet();
ArrayList<Object> results = results(agg);
System.out.println(results.size());
}
public static void main(String[] args) {
TransportClient client = EsClientEnum.INSTANCE.getClient();
QueryBuilder queryBuilder = QueryBuilders.rangeQuery("id").from(0).to(2);
// select count(1) from article group by site,author
SearchResponse searchResponse = client.prepareSearch("article").setTypes("article")
.setQuery(queryBuilder)
.addAggregation(
AggregationBuilders.terms("site").field("site").size(50)
.subAggregation(
AggregationBuilders.terms("author").field("author").size(700)
.subAggregation( AggregationBuilders.count("num").field("site"))
)
)
.execute().actionGet();
AggUtil aggUtil = new AggUtil();
ArrayList<Object> results = aggUtil.results(searchResponse);
for (Object result : results) {
System.out.println(result);
}
}
}
Histogram aggregation
@Test
public void hisGramTest(){
DateHistogramAggregationBuilder aggBuild = AggregationBuilders
.dateHistogram("agg")
.field("time")
.format("yyyy-MM-dd HH:mm:ss")
.dateHistogramInterval(DateHistogramInterval.DAY);
TransportClient client = EsClientEnum.INSTANCE.getClient();
SearchResponse sc = client.prepareSearch("article").setTypes("article")
.addAggregation(aggBuild).get();
Histogram agg = sc.getAggregations().get("agg");
// For each entry
for (Histogram.Bucket entry : agg.getBuckets()) {
String keyAsString = entry.getKeyAsString(); // Key as String
long docCount = entry.getDocCount(); // Doc count
System.out.println(keyAsString+"::::"+docCount);
}
System.out.println("-------------------");
}
来源
Elasticsearch系列(五)----JAVA客户端之TransportClient操作详解_yinni11的博客-CSDN博客_java transportclient
elasticsearch(六)调用TransportClient查询结果处理_胡易卿的博客-CSDN博客_transportclient 查询 Elasticsearch(Transport Client)常用操作_含江君的博客-CSDN博客_elasticsearch transportclient
更多推荐
所有评论(0)