irpas技术客

Java 操作ElasticSearch API 大全,涵盖所有操作方式_緑水長流*z

大大的周 6355

内容简介:包括TransportClient、Low Level Rest Client、High Level Rest Cliet的详细用法,此外还包括高亮搜索、聚合搜索、SQL搜索、SpringDataElasticSearch的Template搜索,Repositories搜索等;涵盖Java操作ElasticSearch的所有API!

文章目录 一、ElasticSearch Java API1.1 搭建环境1.1.1 Maven依赖1.1.2 实体类1.1.3 建立连接 1.2 TransportClient 的用法1.2.1 索引相关1)prepareXxx相关方法2)封装Request相关方法 1.2.2 文档相关1)preapeXxx相关方法2)封装Request相关方法 1.2.3 搜索相关功能1)SearchRequest搜索2)TransportClient搜索 1.2.4 高亮搜索1.2.5 聚合搜索 1.3 Low Level REST Client1.4 High Level REST Client1.5 SQL搜索ElasticSearch1)开启ES白金版功能2)示例代码 二、Spring Data ElasticSearch2.1 Template 查询2.2 Repositories 查询2.2.1 普通增删改查2.2.2 自定义方法命名查询 记得点赞~~

一、ElasticSearch Java API

ElasticSearch官方支持当下几乎所有流行编程语言,如Java、JavaScript、Ruby、Go、.Net、Python等。并且在ElasticSearch官方中都有非常详细的使用案例介绍:

ElasticSearch的客户端工具官方文档:https://·mon.settings.Settings; import org.elasticsearch.transport.client.PreBuiltTransportClient; import org.junit.Test; /** * @author lscl * @version 1.0 * @intro: */ public class Demo01_ES_Connection { /* TransportClient:建立连接 官网案例: https://·mon.settings.Settings; import org.elasticsearch.common.transport.TransportAddress; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentFactory; import org.elasticsearch.transport.client.PreBuiltTransportClient; import org.junit.After; import org.junit.Before; import org.junit.Test; import java.net.InetAddress; import java.util.Arrays; /** * @author lscl * @version 1.0 * @intro: Java操作ES TransportClient方式 索引管理 * 官网相关案例: https://·mon.settings.Settings; import org.elasticsearch.common.transport.TransportAddress; import org.elasticsearch.transport.client.PreBuiltTransportClient; import org.junit.After; import org.junit.Before; import org.junit.Test; import java.net.InetAddress; import java.util.HashMap; /** * @author lscl * @version 1.0 * @intro: Java操作ES TransportClient方式 索引管理 */ public class Demo03_Index_TransportClient { // 创建Client连接对象 private Settings settings; // es客户端对象 private TransportClient client; @Before public void before() throws Exception { // 创建Client连接对象 settings = Settings.builder().put("cluster.name", "elasticsearch").build(); // 客户端对象 client = new PreBuiltTransportClient(settings) .addTransportAddress(new TransportAddress(InetAddress.getByName("127.0.0.1"), 9300)); } @After public void after() throws Exception { client.close(); } // 创建索引 @Test public void test1() throws Exception { // 创建客户端管理对象 AdminClient adminClient = client.admin(); // 获取索引操作对象 IndicesAdminClient indices = adminClient.indices(); // 创建索引请求对象(具体用法: https://·mon.settings.Settings; import org.elasticsearch.common.transport.TransportAddress; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentFactory; import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.transport.client.PreBuiltTransportClient; import org.junit.After; import org.junit.Before; import org.junit.Test; import java.net.InetAddress; import java.util.Map; /** * @author lscl * @version 1.0 * @intro: Java操作ES TransportClient方式 文档管理 */ public class Demo04_Document_TransportClient_Prepare { // 创建Client连接对象 private Settings settings; // es客户端对象 private TransportClient client; @Before public void before() throws Exception { // 创建Client连接对象 settings = Settings.builder().put("cluster.name", "elasticsearch").build(); // 客户端对象 client = new PreBuiltTransportClient(settings) .addTransportAddress(new TransportAddress(InetAddress.getByName("127.0.0.1"), 9300)); } @After public void after() throws Exception { client.close(); } // 新增文档 @Test public void test1() throws Exception { // 准备json数据 Goods goods = new Goods("1", "xiaomi shouji", "xiaomi 5G paizhao shouji", 2899.0D, new String[]{"5G", "paizhao"} ); ObjectMapper objectMapper = new ObjectMapper(); // 转换为JSON字符串 String goodsJson = objectMapper.writeValueAsString(goods); // 执行请求 client.prepareIndex("goodsindex", "_doc", "1").setSource(goodsJson, XContentType.JSON).get(); } // XContentBuilder方式构建文档 @Test public void test2() throws Exception { //创建文档信息 XContentBuilder builder = XContentFactory.jsonBuilder() .startObject() .field("id", "2") .field("name", "huawei shouji") .field("title", "huawei 4G youxi shouji") .field("price", 988) .field("category", new String[]{"4G", "youxi"}) .endObject(); // 建立文档对象 client.prepareIndex("goodsindex", "_doc", "2").setSource(builder).get(); } // 删除文档 @Test public void test3() throws Exception { client.prepareDelete("goodsindex", "_doc", "1").get(); } // 修改文档 @Test public void test4() throws Exception { Goods goods = new Goods("2", "lianxian shouji", "lianxiang 5G youxi shouji", 3899.0D, new String[]{"5G", "youxi"} ); ObjectMapper om = new ObjectMapper(); // 转换为JSON字符串 String goodsJson = om.writeValueAsString(goods); // 执行请求 client.prepareUpdate("goodsindex", "_doc", "2").setDoc(goodsJson, XContentType.JSON).get(); } // 查询文档 @Test public void test5() throws Exception { // 执行查询 GetResponse response = client.prepareGet("goodsindex", "_doc", "1").get(); // 查询结果以Map形式返回 Map<String, Object> sourceAsMap = response.getSourceAsMap(); System.out.println("map: " + sourceAsMap); // 查询结果以Json字符串形式返回 String jsonStr = response.getSourceAsString(); System.out.println("jsonStr: " + jsonStr); } } 2)封装Request相关方法 代码示例: package com.es.demo; import com.es.entity.Goods; import com.fasterxml.jackson.databind.ObjectMapper; import org.elasticsearch.action.delete.DeleteRequest; import org.elasticsearch.action.get.GetRequest; import org.elasticsearch.action.get.GetResponse; import org.elasticsearch.action.index.IndexRequest; import org.elasticsearch.action.update.UpdateRequest; import org.elasticsearch.client.transport.TransportClient; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.transport.TransportAddress; import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.transport.client.PreBuiltTransportClient; import org.junit.After; import org.junit.Before; import org.junit.Test; import java.net.InetAddress; import java.util.Map; /** * @author lscl * @version 1.0 * @intro: Java操作ES TransportClient方式 文档管理 * 官网相关案例: */ public class Demo05_Document_TransportClient { // 创建Client连接对象 private Settings settings; // es客户端对象 private TransportClient client; @Before public void before() throws Exception { // 创建Client连接对象 settings = Settings.builder().put("cluster.name", "elasticsearch").build(); // 客户端对象 client = new PreBuiltTransportClient(settings) .addTransportAddress(new TransportAddress(InetAddress.getByName("127.0.0.1"), 9300)); } @After public void after() throws Exception { client.close(); } // 新增文档 @Test public void test1() throws Exception { // 准备json数据 Goods goods = new Goods("1", "xiaomi shouji", "xiaomi 5G paizhao shouji", 2899.0D, new String[]{"5G", "paizhao"} ); ObjectMapper objectMapper = new ObjectMapper(); String goodsJson = objectMapper.writeValueAsString(goods); // 创建索引请求对象 IndexRequest indexRequest = new IndexRequest("goodsindex", "_doc", "1"); // 传递json数据 indexRequest.source(goodsJson, XContentType.JSON); // 执行请求 client.index(indexRequest).get(); } // 删除文档 @Test public void test2() throws Exception { client.delete(new DeleteRequest("goodsindex", "_doc", "1")).get(); } // 修改文档 @Test public void test3() throws Exception { // 准备Update请求 UpdateRequest updateRequest = new UpdateRequest("goodsindex", "_doc", "2"); Goods goods = new Goods("1", "lianxian shouji", "lianxiang 5G youxi shouji", 3899.0D, new String[]{"5G", "youxi"} ); ObjectMapper om = new ObjectMapper(); // 设置新文档 updateRequest.doc(om.writeValueAsString(goods), XContentType.JSON); // 执行update请求 client.update(updateRequest).get(); } // 查询文档 @Test public void test4() throws Exception { // 准备一个get请求 GetRequest getRequest = new GetRequest("goodsindex", "_doc", "2"); // 执行get请求 GetResponse res = client.get(getRequest).get(); // 获取map数据 Map<String, Object> goodsMap = res.getSource(); System.out.println(goodsMap); // 获取json数据 String goodsJson = res.getSourceAsString(); System.out.println(goodsJson); } } 1.2.3 搜索相关功能 准备数据: DELETE goodsindex POST /goodsindex/_doc/1 { "name":"huawei shouji", "title":"huawei 4G quanmianping youxi shouji", "price":4899, "category":["youxi","4G","quanmianping"] } POST /goodsindex/_doc/2 { "name":"vivo shouji", "title":"vivo 5G paizhao shouji", "price":2899, "category":["5G","paizhao"] } POST /goodsindex/_doc/3 { "name":"oppo shouji", "title":"oppo 5G paizhao shouji", "price":1899, "category":["5G","paizhao"] } POST /goodsindex/_doc/4 { "name":"huawei shouji", "title":"huawei 5G youxi shouji", "price":3899, "category":["5G","youxi"] } POST /goodsindex/_doc/5 { "name":"xiaomi shouji", "title":"xiaomi 4G youxi shouji", "price":988, "category":["youxi","4G"] } POST /goodsindex/_doc/6 { "name":"xiaomi shouji", "title":"xiaomi 5G youxi qumianping shouji", "price":1899, "category":["youxi","5G","qumianping"] } POST /goodsindex/_doc/7 { "name":"xiaomi shouji", "title":"xiaomi 5G youxi shouji", "price":1299, "category":["youxi","5G"] } POST /goodsindex/_doc/8 { "name":"xiaomi shouji", "title":"xiaomi 4G shouji", "price":869, "category":["4G"] } POST /goodsindex/_doc/9 { "name":"huawei shouji", "title":"huawei 5G zhineng qumianping shouji", "price":2899, "category":["zhineng","5G","qumianping"] } POST /goodsindex/_doc/10 { "name":"youxi shouji", "title":"xiaomi 5G shouji", "price":2899, "category":["youxi","5G"] } 1)SearchRequest搜索

SearchRequest:是ES提供的一个专门用于搜索的对象;在创建SearchRequest对象时指定要操作的索引(默认情况下在所有索引中搜索),SearchRequest可以执行封装大部分的搜索;例如string search、queryDSL、query filter、phrase search、term query、query string、highlight search、聚合搜索等;

SearchSourceBuilder:搜索源构建对象,在此对象中设置搜索的条件;最终将SearchSourceBuilder类设置到SearchRequest中,代表填充条件完毕;

QueryBuilders:查询条件构建对象,用于构建不同类型的查询;

QueryBuilders中的方法对应查询matchQuery/matchAllQueryqueryDSLboolQuery/must/mustNotquery filtermatchPhraseQueryphrase searchtermQueryterm queryqueryStringQueryquery string/string search

QueryBuilders更多用法:https://·mon.settings.Settings; import org.elasticsearch.common.transport.TransportAddress; import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.search.SearchHit; import org.elasticsearch.search.SearchHits; import org.elasticsearch.search.sort.SortOrder; import org.elasticsearch.transport.client.PreBuiltTransportClient; import org.junit.After; import org.junit.Before; import org.junit.Test; import java.net.InetAddress; /** * @author lscl * @version 1.0 * @intro: Java操作ES TransportClients的prepareSearch搜索 * 官网相关案例: */ public class Demo06_Search_TransportClient_Prepare { // 创建Client连接对象 private Settings settings; // es客户端对象 private TransportClient client; @Before public void before() throws Exception { // 创建Client连接对象 settings = Settings.builder().put("cluster.name", "elasticsearch").build(); // 客户端对象 client = new PreBuiltTransportClient(settings) .addTransportAddress(new TransportAddress(InetAddress.getByName("127.0.0.1"), 9300)); } @After public void after() throws Exception { client.close(); } // 抽取打印方法 public void print(SearchResponse res) { System.out.println("查询到: " + res.getHits().getTotalHits().value); SearchHits hits = res.getHits(); for (SearchHit hit : hits) { System.out.println("score: " + hit.getScore()); // 文档的json返回形式 System.out.println(hit.getSourceAsString()); System.out.println("------------"); } } // DSL query @Test public void queryDSL() throws Exception { // 创建搜索条件对象 SearchResponse res = client.prepareSearch("goodsindex") .setTypes("_doc") .setQuery(QueryBuilders.matchQuery("title", "xiaomi")) .get(); print(res); } // query filter @Test public void queryFilter() throws Exception { SearchResponse res = client.prepareSearch("goodsindex") .setQuery( QueryBuilders.boolQuery() .must(QueryBuilders.matchQuery("title", "huawei")) .mustNot(QueryBuilders.matchQuery("title", "youxi")) ).get(); print(res); } // phrase search @Test public void phraseSearch() throws Exception { SearchResponse res = client.prepareSearch("goodsindex") .setQuery(QueryBuilders.matchPhraseQuery("title", "huawei 5G")) .get(); print(res); } // term query @Test public void termQuery() throws Exception { SearchResponse res = client.prepareSearch("goodsindex") .setQuery(QueryBuilders.termQuery("title", "huawei 5G")) .get(); print(res); } // string search @Test public void stringSearch() throws Exception { // 带分词 // 创建搜索条件对象 SearchResponse res = client.prepareSearch("goodsindex") .setTypes("_doc") .setQuery(QueryBuilders.queryStringQuery("title:4G")) .setQuery(QueryBuilders.queryStringQuery("category:youxi")) .setQuery(QueryBuilders.queryStringQuery("price:[2000 TO 5000]")) .addSort("price", SortOrder.DESC) .setFrom(0) .setSize(3) .get(); print(res); } // query string @Test public void queryString() throws Exception { SearchResponse res = client.prepareSearch("goodsindex") .setQuery( // AND/OR 运算符查询 // QueryBuilders.queryStringQuery("youxi 5G").field("name").field("title").defaultOperator(Operator.AND) // 最少匹配词条 // QueryBuilders.queryStringQuery("huawei youxi 4G").field("title").minimumShouldMatch("2") // 模糊查询 // QueryBuilders.queryStringQuery("huawkk~").field("title") // 范围查询 QueryBuilders.queryStringQuery("[2000 TO 3000]").field("price") ) .get(); print(res); } // ids query @Test public void testIdQuery() throws Exception { SearchResponse res = client.prepareSearch("goodsindex") .setTypes("article") //设置要查询的id .setQuery(QueryBuilders.idsQuery().addIds("1", "2")) //执行查询 .get(); print(res); } } 2)TransportClient搜索

使用TransportClient类提供的prepareSearch方法进行搜索,同样使用QueryBuilders进行搜索条件的构建,只是写法不同而已;

代码示例: package com.es.demo; import org.elasticsearch.action.search.SearchRequest; import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.client.transport.TransportClient; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.transport.TransportAddress; import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.search.SearchHit; import org.elasticsearch.search.SearchHits; import org.elasticsearch.search.builder.SearchSourceBuilder; import org.elasticsearch.search.sort.SortOrder; import org.elasticsearch.transport.client.PreBuiltTransportClient; import org.junit.After; import org.junit.Before; import org.junit.Test; import java.net.InetAddress; /** * @author lscl * @version 1.0 * @intro: Java操作ES * 官网相关案例: */ public class Demo07_Search_TransportClient { // 创建Client连接对象 private Settings settings; // es客户端对象 private TransportClient client; // 抽取打印方法 public void print(SearchResponse res) { System.out.println("查询到: " + res.getHits().getTotalHits().value); SearchHits hits = res.getHits(); for (SearchHit hit : hits) { System.out.println("score: " + hit.getScore()); // 文档的json返回形式 System.out.println(hit.getSourceAsString()); System.out.println("------------"); } } @Before public void before() throws Exception { // 创建Client连接对象 settings = Settings.builder().put("cluster.name", "my-cluster").build(); // 客户端对象 client = new PreBuiltTransportClient(settings) .addTransportAddress(new TransportAddress(InetAddress.getByName("127.0.0.1"), 9300)); System.out.println(client.getClass()); } @After public void after() throws Exception { client.close(); } // query string @Test public void stringSearch() throws Exception { // 带分词 // 创建搜索对象 SearchRequest searchRequest = new SearchRequest("goodsindex"); // 创建查询构建对象 SearchSourceBuilder builder = new SearchSourceBuilder(); // 设置查询条件 builder.query(QueryBuilders.queryStringQuery("title:shou*")); builder.query(QueryBuilders.queryStringQuery("category:youxi")); builder.query(QueryBuilders.queryStringQuery("price:[2000 TO 5000]")); builder.sort("price", SortOrder.DESC); builder.from(0); builder.size(2); // 封装查询 searchRequest.source(builder); // 执行查询获取结果集 SearchResponse res = client.search(searchRequest).get(); System.out.println("查询到: " + res.getHits().getTotalHits().value); SearchHits hits = res.getHits(); for (SearchHit hit : hits) { System.out.println("score: " + hit.getScore()); // 文档的json返回形式 System.out.println(hit.getSourceAsString()); System.out.println("------------"); } } // DSL query @Test public void queryDSL() throws Exception { // 创建搜索请求对象 SearchRequest searchRequest = new SearchRequest("goodsindex"); // 创建查询构建对象 SearchSourceBuilder builder = new SearchSourceBuilder(); // 设置查询条件 // builder.query(QueryBuilders.matchAllQuery()); builder.query(QueryBuilders.matchQuery("title", "xiaomi")); // 封装查询 searchRequest.source(builder); // 执行查询获取结果集 SearchResponse res = client.search(searchRequest).get(); // 打印结果集 print(res); } // query filter @Test public void queryFilter() throws Exception { SearchRequest searchRequest = new SearchRequest("goodsindex"); // 创建查询构建对象 SearchSourceBuilder builder = new SearchSourceBuilder(); // 构建查询条件 builder.query( QueryBuilders.boolQuery(). must(QueryBuilders.matchQuery("title", "huawei")). mustNot(QueryBuilders.matchQuery("title", "youxi")) ); // 封装查询条件 searchRequest.source(builder); SearchResponse res = client.search(searchRequest).get(); print(res); } // phrase query @Test public void phraseSearch() throws Exception { // 创建搜索请求对象 SearchRequest searchRequest = new SearchRequest("goodsindex"); // 创建查询构建对象 SearchSourceBuilder builder = new SearchSourceBuilder(); // 设置查询条件 builder.query(QueryBuilders.matchPhraseQuery("title", "huawei 5G")); // 封装查询 searchRequest.source(builder); // 执行查询获取结果集 SearchResponse res = client.search(searchRequest).get(); // 打印结果集 print(res); } // term query @Test public void termQuery() throws Exception { // 创建搜索请求对象 SearchRequest searchRequest = new SearchRequest("goodsindex"); // 创建查询构建对象 SearchSourceBuilder builder = new SearchSourceBuilder(); // 设置查询条件 builder.query(QueryBuilders.termQuery("title", "huawei 5G")); // 封装查询 searchRequest.source(builder); // 执行查询获取结果集 SearchResponse res = client.search(searchRequest).get(); // 打印结果集 print(res); } // query string @Test public void queryString() throws Exception { // 创建搜索请求对象 SearchRequest searchRequest = new SearchRequest("goodsindex"); // 创建查询构建对象 SearchSourceBuilder builder = new SearchSourceBuilder(); // 设置查询条件 builder.query( // AND/OR 运算符查询 // QueryBuilders.queryStringQuery("youxi 5G").field("name").field("title").defaultOperator(Operator.AND) // 最少匹配词条 // QueryBuilders.queryStringQuery("huawei youxi 4G").field("title").minimumShouldMatch("2") // 模糊查询 // QueryBuilders.queryStringQuery("huawkk~").field("title") // 范围查询 QueryBuilders.queryStringQuery("[2000 TO 3000]").field("price") ); // 封装查询 searchRequest.source(builder); // 执行查询获取结果集 SearchResponse res = client.search(searchRequest).get(); // 打印结果集 print(res); } } 1.2.4 高亮搜索

Java在实现ES的高亮搜索主要就在于一个类:HighlightBuilder。该类封装了高亮搜索的条件,如高亮字段/高亮前后缀等;

HighlightBuilder具体用法:https://·mon.settings.Settings; import org.elasticsearch.common.transport.TransportAddress; import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.search.SearchHit; import org.elasticsearch.search.SearchHits; import org.elasticsearch.search.builder.SearchSourceBuilder; import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder; import org.elasticsearch.search.fetch.subphase.highlight.HighlightField; import org.elasticsearch.transport.client.PreBuiltTransportClient; import org.junit.After; import org.junit.Before; import org.junit.Test; import java.net.InetAddress; import java.util.Map; /** * @author lscl * @version 1.0 * @intro: 使用TransportClient进行高亮搜索 */ public class Demo08_Highlight_Search_TransportClient { // 创建Client连接对象 private Settings settings; // es客户端对象 private TransportClient client; // 抽取打印方法 public void print(SearchResponse res) { System.out.println("查询到: " + res.getHits().getTotalHits().value); SearchHits hits = res.getHits(); for (SearchHit hit : hits) { System.out.println("score: " + hit.getScore()); // 文档的json返回形式 System.out.println(hit.getSourceAsString()); System.out.println("------------"); } } @Before public void before() throws Exception { // 创建Client连接对象 settings = Settings.builder().put("cluster.name", "elasticsearch").build(); // 客户端对象 client = new PreBuiltTransportClient(settings) .addTransportAddress(new TransportAddress(InetAddress.getByName("127.0.0.1"), 9300)); } @After public void after() throws Exception { client.close(); } // 使用SearchRequest对象进行高亮搜索 @Test public void searchQueryHighQuery() throws Exception { // 准备一个SearchRequest对象 SearchRequest searchRequest = new SearchRequest("goodsindex"); // 搜索条件构建对象 SearchSourceBuilder builder = new SearchSourceBuilder(); // 设置搜索条件 builder.query(QueryBuilders.queryStringQuery("title:4G")); // 高亮构建对象 HighlightBuilder highBuilder = new HighlightBuilder().field("title").preTags("<font color='red'>").postTags("</font>"); // 设置高亮 builder.highlighter(highBuilder); // 设置查询源 searchRequest.source(builder); // 执行查询 SearchResponse res = client.search(searchRequest).get(); // 获取命中的记录 SearchHits results = res.getHits(); for (SearchHit result : results) { // 原始数据 String sourceAsString = result.getSourceAsString(); System.out.println(sourceAsString); // 高亮数据 Map<String, HighlightField> high = result.getHighlightFields(); System.out.println(high.get("title").fragments()[0].string()); System.out.println("----------------"); } } // 使用prepareSearch进行查询 @Test public void transportClientHighQuery() throws Exception { // 高亮条件构造器 HighlightBuilder highBuilder = new HighlightBuilder().field("title").preTags("</font style='red'>").postTags("</font>"); // 创建搜索条件对象 SearchResponse res = client.prepareSearch("goodsindex") .setTypes("_doc") .setQuery(QueryBuilders.queryStringQuery("title:4G")) .highlighter(highBuilder) // 设置高亮数据 .get(); // 获取命中的记录 SearchHits results = res.getHits(); for (SearchHit result : results) { // 原始数据 String sourceAsString = result.getSourceAsString(); System.out.println(sourceAsString); // 高亮数据 Map<String, HighlightField> high = result.getHighlightFields(); System.out.println(high.get("title").fragments()[0].string()); System.out.println("----------------"); } } } 1.2.5 聚合搜索 示例代码: package com.es.demo; import org.elasticsearch.action.search.SearchRequest; import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.client.transport.TransportClient; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.transport.TransportAddress; import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.search.SearchHit; import org.elasticsearch.search.SearchHits; import org.elasticsearch.search.aggregations.AggregationBuilders; import org.elasticsearch.search.aggregations.Aggregations; import org.elasticsearch.search.aggregations.bucket.terms.Terms; import org.elasticsearch.search.builder.SearchSourceBuilder; import org.elasticsearch.transport.client.PreBuiltTransportClient; import org.junit.After; import org.junit.Before; import org.junit.Test; import java.net.InetAddress; import java.util.List; /** * @author lscl * @version 1.0 * @intro: 使用TransportClient进行聚合搜索 */ public class Demo09_Aggs_TransportClient { // 创建Client连接对象 private Settings settings; // es客户端对象 private TransportClient client; // 抽取打印方法 public void print(SearchResponse res) { System.out.println("查询到: " + res.getHits().getTotalHits().value); SearchHits hits = res.getHits(); for (SearchHit hit : hits) { System.out.println("score: " + hit.getScore()); // 文档的json返回形式 System.out.println(hit.getSourceAsString()); System.out.println("------------"); } } @Before public void before() throws Exception { // 创建Client连接对象 settings = Settings.builder().put("cluster.name", "my-cluster").build(); // 客户端对象 client = new PreBuiltTransportClient(settings) .addTransportAddress(new TransportAddress(InetAddress.getByName("127.0.0.1"), 9300)); } @After public void after() throws Exception { client.close(); } // 计算每个分类下的商品数量(使用SearchRequest进行搜索) @Test public void aggs_searchRequest() throws Exception { // 创建搜索对象 SearchRequest searchRequest = new SearchRequest("goodsindex"); // 条件构建对象 SearchSourceBuilder searchBuilder = new SearchSourceBuilder().aggregation(AggregationBuilders.terms("group_by_category").field("category")); // 设置搜索条件 searchRequest.source(searchBuilder); // 执行搜索 SearchResponse res = client.search(searchRequest).get(); // 获取聚合数据 Aggregations aggregations = res.getAggregations(); // 根据分组的名称获取对应的值 Terms group_by_category = aggregations.get("group_by_category"); // 获取 List<? extends Terms.Bucket> buckets = group_by_category.getBuckets(); for (Terms.Bucket bucket : buckets) { // key String key = bucket.getKeyAsString(); System.out.println("key:" + key); // docCount long docCount = bucket.getDocCount(); System.out.println("docCount:" + docCount); System.out.println("--------------------"); } } // 计算每个分类下的商品数量(使用prepareSearch进行搜索) @Test public void aggs_transportClientSearch() throws Exception { /* GET goodsindex/_doc/_search { "size": 0, "aggs": { "group_by_category": { "terms": { "field": "category" } } } } */ SearchResponse res = client.prepareSearch("goodsindex") .setQuery(QueryBuilders.matchAllQuery()) .addAggregation(AggregationBuilders.terms("group_by_category").field("category")) .setSize(0) // 不要原始数据(只要聚合数据) .get(); // 获取聚合数据 Aggregations aggregations = res.getAggregations(); // 根据分组的名称获取对应的值 Terms group_by_category = aggregations.get("group_by_category"); // 获取 List<? extends Terms.Bucket> buckets = group_by_category.getBuckets(); for (Terms.Bucket bucket : buckets) { // key String key = bucket.getKeyAsString(); System.out.println("key:" + key); // docCount long docCount = bucket.getDocCount(); System.out.println("docCount:" + docCount); System.out.println("--------------------"); } } } 1.3 Low Level REST Client

Low Level REST Client:ElasticSearch官方的低级客户端。之所以称为低级客户端,是因为它几乎没有帮助 Java 用户构建请求或解析响应。它只处理请求的路径和查询字符串构造;请求响应后,只是将响应的数据直接响应给客户端,并没有做其他处理;

官方文档:https://·mon.xcontent.XContentType; import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.search.SearchHit; import org.elasticsearch.search.SearchHits; import org.elasticsearch.search.builder.SearchSourceBuilder; import org.junit.After; import org.junit.Before; import org.junit.Test; /** * @author lscl * @version 1.0 * @intro: RestHighLevelClient 用法 */ public class Demo11_RestHighLevelClient { // 高级查询对象 private RestHighLevelClient client; // 抽取打印方法 public void print(SearchResponse res) { System.out.println("查询到: " + res.getHits().getTotalHits().value); SearchHits hits = res.getHits(); for (SearchHit hit : hits) { System.out.println("score: " + hit.getScore()); // 文档的json返回形式 System.out.println(hit.getSourceAsString()); System.out.println("------------"); } } @Before public void before() throws Exception { //获取连接客户端 client = new RestHighLevelClient( RestClient.builder( new HttpHost("localhost", 9200, "http") ) ); } @After public void after() throws Exception { client.close(); } @Test public void insert() throws Exception { // 增 // 准备数据 Goods goods = new Goods("11", "meizu shouji", "meizu 5G zhineng paizhao shouji", 2899.0D, new String[]{"5G", "zhineng", "paizhao"} ); // 转换为json String goodsJson = new ObjectMapper().writeValueAsString(goods); // 准备索引请求对象 IndexRequest indexRequest = new IndexRequest("goodsindex", "_doc", "11"); // 设置数据源 indexRequest.source(goodsJson, XContentType.JSON); client.index(indexRequest, RequestOptions.DEFAULT); } @Test public void delete() throws Exception { // 删 DeleteRequest deleteRequest = new DeleteRequest("goodsindex", "_doc", "1"); client.delete(deleteRequest, RequestOptions.DEFAULT); } @Test public void update() throws Exception { // 改 UpdateRequest updateRequest = new UpdateRequest("goodsindex", "_doc", "2"); // 准备数据 Goods goods = new Goods("2", "zhongxing shouji", "zhongxing 4G youxi shouji", 2899.0D, new String[]{"4G", "youxi"}); String goodsJson = new ObjectMapper().writeValueAsString(goods); updateRequest.doc(goodsJson, XContentType.JSON); client.update(updateRequest, RequestOptions.DEFAULT); } @Test public void query() throws Exception { // 查 GetRequest getRequest = new GetRequest("goodsindex", "_doc", "2"); GetResponse res = client.get(getRequest, RequestOptions.DEFAULT); System.out.println(res.getSourceAsString()); } @Test public void searchRequest() throws Exception { // searchRequest查询 SearchRequest searchRequest = new SearchRequest("goodsindex"); SearchSourceBuilder builder = new SearchSourceBuilder() .query(QueryBuilders.queryStringQuery("title:meizu")); searchRequest.source(builder); SearchResponse res = client.search(searchRequest, RequestOptions.DEFAULT); print(res); } } 1.5 SQL搜索ElasticSearch 1)开启ES白金版功能 1)

2)

3):

4):

2)示例代码 引入相关依赖: <!--配置ES的SQL支持 maven仓库--> <repositories> <repository> <id>elastic.co</id> <url>https://artifacts.elastic.co/maven</url> </repository> </repositories> <dependencies> <dependency> <groupId>org.elasticsearch.plugin</groupId> <artifactId>x-pack-sql-jdbc</artifactId> <version>7.6.2</version> </dependency> </dependencies> 示例代码: package com.es.demo; import org.junit.Test; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.Statement; /** * @author lscl * @version 1.0 * @intro: */ public class Demo12_ES_JDBC { @Test public void test1() throws Exception { // 获取与ES服务器的连接 Connection connection = DriverManager.getConnection("jdbc:es://http://localhost:9200"); // 创建语句对象 Statement statement = connection.createStatement(); // 执行SQL,获取结果集 ResultSet rs = statement.executeQuery("select * from goodsindex"); while (rs.next()) { System.out.print("name: " + rs.getString("name")+"\t"); System.out.print("title: " + rs.getString("title")+"\t"); System.out.print("price: " + rs.getString("price")+"\t"); System.out.print("category: " + rs.getString("category")+"\t"); System.out.println(); } connection.close(); } } 二、Spring Data ElasticSearch

Spring Data ElasticSearch是SpringData大家族的一员,Spring Data 的使命是给各种数据访问提供统一的编程接口,不管是关系型数据库(如MySQL),还是非关系数据库(如Redis),或者类似Elasticsearch这样的索引数据库。从而简化开发人员的代码,提高开发效率。

SpringData官网:https://spring.io/projects/spring-dataSpringDataElasticSearch官网:https://docs.spring.io/spring-data/elasticsearch/docs/4.0.3.RELEASE/reference/html/#preface

引入项目依赖: <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.es</groupId> <artifactId>02_ElasticSearch_Template</artifactId> <version>1.0-SNAPSHOT</version> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.3.1.RELEASE</version> <relativePath/> </parent> <!--锁定ES版本--> <properties> <elasticsearch.version>7.6.2</elasticsearch.version> </properties> <dependencies> <!--SpringBoot整合Elasticsearch--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-elasticsearch</artifactId> </dependency> <!--SpringBoot整合测试单元--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> </dependency> <!--lombok插件--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.12</version> </dependency> </dependencies> </project> 2.1 Template 查询

SpringData家族为大部分产品都提供了查询模板类,例如JdbcTemplate、RedisTemplate、RabbitTempalte等简化我们的操作;同样,SpringDataElasticSearch提供了ElasticsearchRestTemplate类来简化Java操作ES的代码;

SpringDataElasticSearch官网案例:https://docs.spring.io/spring-data/elasticsearch/docs/4.0.3.RELEASE/reference/html/#elasticsearch.operations 在SpringDataElasticSearch官网中提供有四种操作ES的相关类: IndexOperations:有关于索引相关操作,如创建或删除索引。DocumentOperations:有关于文档的操作,根据文档的id进行存储、更新和检索文档的操作。SearchOperations:搜索文档相关操作ElasticsearchOperations :结合了DocumentOperations和SearchOperations接口。

Spring官网中提供有ElasticsearchTemplate与ElasticsearchRestTemplate 两个ES相关模板类,其中ElasticsearchTemplate是使用TransportClient对ElasticsearchOperations的实现;ElasticsearchRestTemplate 则是使用High Level REST Client对ElasticsearchOperations的实现;

Tips:ElasticsearchTemplate从4.0版本起不再使用,使用ElasticsearchRestTemplate代替。


定义实体类:

关于实体类定义的详细文档:https://docs.spring.io/spring-data/elasticsearch/docs/4.0.3.RELEASE/reference/html/#elasticsearch.mapping

package com.es.entity; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import org.springframework.data.annotation.Id; import org.springframework.data.elasticsearch.annotations.Document; import org.springframework.data.elasticsearch.annotations.Field; import org.springframework.data.elasticsearch.annotations.FieldType; @Data @AllArgsConstructor @NoArgsConstructor @Document(indexName = "goodsindex", type = "_doc", shards = 1, replicas = 2) // ES7.0后不支持type功能(一个索引只能有一个type,名为_doc) public class Goods { @Id private String id; @Field(index = true, store = false, fielddata = false, type = FieldType.Text, analyzer = "standard", searchAnalyzer = "standard") private String name; @Field(analyzer = "standard", searchAnalyzer = "standard") private String title; @Field private Double price; @Field private String[] category; } XxxOperations示例代码: import com.es.Application; import com.es.entity.Goods; import org.elasticsearch.index.query.QueryBuilders; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.data.elasticsearch.core.*; import org.springframework.data.elasticsearch.core.query.NativeSearchQuery; import org.springframework.test.context.junit4.SpringRunner; @SpringBootTest(classes = Application.class) @RunWith(SpringRunner.class) public class Demo01_Options { @Autowired private DocumentOperations documentOperations; @Autowired private SearchOperations searchOperations; @Autowired private ElasticsearchOperations elasticsearchOperations; @Autowired private ElasticsearchRestTemplate elasticsearchRestTemplate; @Test public void test1() { // 获取IndexOperations索引操作对象 IndexOperations indexOperations = elasticsearchOperations.indexOps(Goods.class); // 创建索引 indexOperations.create(); } @Test public void test2() { Goods goods = new Goods( "1", "xiaomi shouji", "xiaomi 5g youxi shouji", 2000.0D, new String[]{"5g", "youxi"} ); documentOperations.save(goods); } @Test public void test3() { // 本地查询 NativeSearchQuery query = new NativeSearchQuery(QueryBuilders.matchAllQuery()); SearchHits<Goods> searchHits = searchOperations.search(query, Goods.class); for (SearchHit<Goods> searchHit : searchHits) { Goods goods = searchHit.getContent(); System.out.println(goods); } } @Test public void test4() { Goods goods = elasticsearchOperations.get("1", Goods.class); System.out.println(goods); } } ElasticsearchRestTemplate 示例代码: import com.es.Application; import com.es.entity.Goods; import org.elasticsearch.index.query.QueryBuilders; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate; import org.springframework.data.elasticsearch.core.SearchHit; import org.springframework.data.elasticsearch.core.SearchHits; import org.springframework.data.elasticsearch.core.document.Document; import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; import org.springframework.data.elasticsearch.core.query.NativeSearchQuery; import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder; import org.springframework.data.elasticsearch.core.query.UpdateQuery; import org.springframework.test.context.junit4.SpringRunner; @SpringBootTest(classes = Application.class) @RunWith(SpringRunner.class) public class Demo02_Template { @Autowired private ElasticsearchRestTemplate restTemplate; @Test public void insert() { // insert Goods goods = new Goods( "1", "huawei shouji", "huawei 5G youxi shouji", 1889.0D, new String[]{"youxi", "5G"} ); restTemplate.save(goods, IndexCoordinates.of("goodsindex")); } @Test public void delete() { // delete restTemplate.delete("2", IndexCoordinates.of("goodsindex")); } @Test public void update() { Document goodsDoc = Document.create(); goodsDoc.append("id", "1"); goodsDoc.append("name", "meizu shouji"); goodsDoc.append("title", "meizu 4G paizhao shouji"); goodsDoc.append("double", 1889.0D); goodsDoc.append("category", new String[]{"paizhao", "4G"}); UpdateQuery updateQuery = UpdateQuery.builder("1") .withDocument(goodsDoc) .build(); restTemplate.update(updateQuery, IndexCoordinates.of("goodsindex")); } @Test public void query() { // query Goods goods = restTemplate.get("1", Goods.class, IndexCoordinates.of("goodsindex")); System.out.println(goods); } @Test public void queryForNative() { // 使用本地查询 // 使用本地搜索查询(原生ES的API查询) NativeSearchQuery query = new NativeSearchQueryBuilder() .withQuery(QueryBuilders.matchAllQuery()) .build(); SearchHits<Goods> goodsSearchHits = restTemplate.search(query, Goods.class, IndexCoordinates.of("goodsindex")); for (SearchHit<Goods> goodsHit : goodsSearchHits) { Goods goods = goodsHit.getContent(); System.out.println(goods); } } } 2.2 Repositories 查询 详细文档:https://docs.spring.io/spring-data/elasticsearch/docs/4.0.3.RELEASE/reference/html/#elasticsearch.repositories 实体类(建立映射关系): package com.dfbz.entity; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import org.springframework.data.annotation.Id; import org.springframework.data.elasticsearch.annotations.Document; import org.springframework.data.elasticsearch.annotations.Field; import org.springframework.data.elasticsearch.annotations.FieldType; @Data @AllArgsConstructor @NoArgsConstructor @Document(indexName = "goodsindex", type = "_doc") // ES7.0后不支持type功能(一个索引只能有一个type,名为_doc) public class Goods { @Id private String id; @Field(index = true, store = false, fielddata = false, type = FieldType.Text, analyzer = "standard", searchAnalyzer = "standard") private String name; @Field private String title; @Field private Double price; @Field private String[] category; } Dao接口: package com.dfbz.dao; import com.dfbz.entity.Goods; import org.springframework.data.elasticsearch.repository.ElasticsearchRepository; public interface GoodsDao extends ElasticsearchRepository<Goods,String> { } 2.2.1 普通增删改查 查询示例: package com.dfbz.demo; import com.dfbz.Application; import com.dfbz.dao.GoodsDao; import com.dfbz.entity.Goods; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.data.domain.PageRequest; import org.springframework.test.context.junit4.SpringRunner; import java.util.Arrays; @SpringBootTest(classes = Application.class) @RunWith(SpringRunner.class) public class Demo01_CRUD { @Autowired private GoodsDao goodsDao; @Test public void findAll() { // query // Iterable<Goods> goodsList = goodsDao.findAll(); // 带分页查询 Iterable<Goods> goodsList = goodsDao.findAll(PageRequest.of(2,1)); for (Goods goods : goodsList) { System.out.println(goods); } } @Test public void findById() { // query Goods goods = goodsDao.findById("1").get(); System.out.println(goods); } @Test public void insert() { // insert Goods goods = new Goods( "1", "vivo shouji", "vivo 5G paizhao shouji", 3889.0D, new String[]{"paizhao", "5G"} ); Goods goods2 = new Goods( "2", "meizu shouji", "meizu 4G youxi shouji", 3889.0D, new String[]{"youxi", "5G"} ); // goodsDao.save(goods); goodsDao.saveAll(Arrays.asList(goods,goods2)); } @Test public void update() { Goods goods = new Goods( "8", "oppo shouji", "oppo 5G paizhao shouji", 2889.0D, new String[]{"paizhao", "5G"} ); goodsDao.save(goods); } @Test public void delete() { // delete goodsDao.deleteById("8"); } } 2.2.2 自定义方法命名查询 dao接口: package com.es.dao; import com.es.entity.Goods; import org.springframework.data.elasticsearch.annotations.Highlight; import org.springframework.data.elasticsearch.annotations.HighlightField; import org.springframework.data.elasticsearch.annotations.HighlightParameters; import org.springframework.data.elasticsearch.annotations.Query; import org.springframework.data.elasticsearch.core.SearchHit; import org.springframework.data.elasticsearch.repository.ElasticsearchRepository; import java.util.List; public interface GoodsDao extends ElasticsearchRepository<Goods, String> { List<Goods> findByTitle(String title); List<Goods> findByPriceBetween(Double start, Double end); List<Goods> findByTitleLike(String title); /* GET goodsindex/_doc/_search { "query": { "match": { "title": "shouji" } } } */ // 使用原生的ES查询语句查询 @Query("{\"match\": {\"title\": {\"query\": \"?0\"}}}") List<Goods> searchByQueryString(String title); // 高亮查询 @Highlight( fields = { @HighlightField( name = "name", parameters = @HighlightParameters(preTags = "<font color='red'>",postTags = "</font>") ), @HighlightField( name = "title", parameters = @HighlightParameters(preTags = "<font color='red'>",postTags = "</font>") ) } ) List<SearchHit<Goods>> findByTitleOrName(String title, String name); }

官网参考:https://docs.spring.io/spring-data/elasticsearch/docs/4.0.3.RELEASE/reference/html/#elasticsearch.query-methods.criterions 示例代码: package com.es.demo; import com.es.Application; import com.es.dao.GoodsDao; import com.es.entity.Goods; import org.elasticsearch.index.query.MatchQueryBuilder; import org.elasticsearch.index.query.QueryBuilders; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.data.elasticsearch.core.SearchHit; import org.springframework.test.context.junit4.SpringRunner; import java.util.List; import java.util.Map; @SpringBootTest(classes = Application.class) @RunWith(SpringRunner.class) public class Demo02_NamedQuery { @Autowired private GoodsDao goodsDao; @Test public void findByTitle() { /* GET goodsindex/_doc/_search { "query": { "bool": { "must": [{ "query_string": { "query": "?", "fields": ["name"] } }] } } } */ List<Goods> goodsList = goodsDao.findByTitleLike("x"); for (Goods goods : goodsList) { System.out.println(goods); } } @Test public void findByPriceBetween() { /* GET goodsindex/_doc/_search { "query": { "bool": { "must": [{ "range": { "price": { "from": ? , "to": ? , "include_lower": true, "include_upper": true } } }] } } } */ List<Goods> goodsList = goodsDao.findByPriceBetween(2000.0D, 4000.0D); for (Goods goods : goodsList) { System.out.println(goods); } } @Test public void findByTitleLike() { /* GET goodsindex/_doc/_search { "query": { "bool": { "must": [{ "query_string": { "query": "?*", "fields": ["name"] }, "analyze_wildcard": true }] } } } */ List<Goods> goodsList = goodsDao.findByTitleLike("xiao"); for (Goods goods : goodsList) { System.out.println(goods); } } @Test public void searchQuery() { // searchQuery查询 MatchQueryBuilder searchQuery = QueryBuilders.matchQuery("title", "meizu 5G"); Iterable<Goods> goodsList = goodsDao.search(searchQuery); for (Goods goods : goodsList) { System.out.println(goods); } } @Test public void anno() { // 通过query注解查询 List<Goods> goodsList = goodsDao.searchByQueryString("xiaomi"); for (Goods goods : goodsList) { System.out.println(goods); } } @Test public void highQuery() { // 高亮查询 List<SearchHit<Goods>> goodsList = goodsDao.findByTitleOrName("shouji", "shouji"); for (SearchHit<Goods> goodsHit : goodsList) { // 获取高亮字段的值 Map<String, List<String>> highlightFields = goodsHit.getHighlightFields(); System.out.println(highlightFields); } } }

需要注意的是,SpringDatatElasticSearch支持的query注解查询语法有些变化:

GET goodsindex/_doc/_search { "query": { "match": { "title": "shouji" } } } 改为: GET goodsindex/_doc/_search { "query": { "match": { "title": { "query":"xiaomi" } } } } ------------------------------------------ GET goodsindex/_doc/_search { "query": { "bool": { "must": [ { "match": { "title": "huawei" } } ], "must_not": [ { "match": { "title": "youxi" } } ] } } } 改为: GET goodsindex/_doc/_search { "query": { "bool": { "must": [ { "match": { "title":{ "query":"xiaomi" } } } ], "must_not": [ { "match": { "title": { "query":"youxi" } } } ] } } } --------------------------------------------------------------- GET goodsindex/_doc/_search { "query": { "match": { "title": "xiaomi" } } } 改为: GET goodsindex/_doc/_search { "query": { "match": { "title": { "query": "xiaomi" } } } } 记得点赞~~


1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,会注明原创字样,如未注明都非原创,如有侵权请联系删除!;3.作者投稿可能会经我们编辑修改或补充;4.本站不提供任何储存功能只提供收集或者投稿人的网盘链接。

标签: #JAVA #操作elasticsearch #API #大全 #涵盖所有操作方式 #level #REST