赞
踩
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>7.8.0</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.8.0</version>
</dependency>
import com.alibaba.fastjson.JSONObject; import com.atguigu.estest.model.User; import org.apache.http.HttpHost; import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest; import org.elasticsearch.action.bulk.BulkItemResponse; import org.elasticsearch.action.bulk.BulkRequest; import org.elasticsearch.action.bulk.BulkResponse; import org.elasticsearch.action.delete.DeleteRequest; import org.elasticsearch.action.delete.DeleteResponse; import org.elasticsearch.action.get.*; import org.elasticsearch.action.index.IndexRequest; import org.elasticsearch.action.index.IndexResponse; import org.elasticsearch.action.search.ClearScrollRequest; import org.elasticsearch.action.search.SearchRequest; import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.action.search.SearchScrollRequest; import org.elasticsearch.action.support.IndicesOptions; import org.elasticsearch.action.support.master.AcknowledgedResponse; import org.elasticsearch.action.update.UpdateRequest; import org.elasticsearch.action.update.UpdateResponse; import org.elasticsearch.client.RequestOptions; import org.elasticsearch.client.RestClient; import org.elasticsearch.client.RestHighLevelClient; import org.elasticsearch.client.core.CountRequest; import org.elasticsearch.client.core.CountResponse; import org.elasticsearch.client.indices.CreateIndexRequest; import org.elasticsearch.client.indices.CreateIndexResponse; import org.elasticsearch.client.indices.GetIndexRequest; import org.elasticsearch.client.indices.GetIndexResponse; import org.elasticsearch.common.unit.Fuzziness; import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.index.query.BoolQueryBuilder; import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.index.reindex.BulkByScrollResponse; import org.elasticsearch.index.reindex.DeleteByQueryRequest; import org.elasticsearch.search.Scroll; import org.elasticsearch.search.SearchHit; import org.elasticsearch.search.aggregations.AggregationBuilder; import org.elasticsearch.search.aggregations.AggregationBuilders; import org.elasticsearch.search.aggregations.Aggregations; import org.elasticsearch.search.aggregations.bucket.terms.ParsedStringTerms; import org.elasticsearch.search.aggregations.bucket.terms.Terms; import org.elasticsearch.search.aggregations.metrics.ParsedMax; import org.elasticsearch.search.builder.SearchSourceBuilder; import org.elasticsearch.search.fetch.subphase.FetchSourceContext; 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.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Map;
void addIndex() throws Exception { /** * GET /user * 作用:可以看到aliases、mappings、settings * 说明:我们下面使用的是直接定死的结构,而SpringBoot中使用的是注解的方式来创建索引结构,最终的原理都是下面的代码 * { * "user": { * "aliases": { * "user.aliases": {} * }, * "mappings": { * "properties": { * "age": { * "type": "integer" * }, * "name": { * "type": "text", * "fields": { * "keyword": { * "type": "keyword" * } * } * }, * "sex": { * "type": "keyword" * } * } * }, * "settings": { * "index": { * "creation_date": "1649243890532", * "number_of_shards": "9", * "number_of_replicas": "2", * "uuid": "EPChtL_vQj2gHJbO5VTHqg", * "version": { * "created": "7060099" * }, * "provided_name": "user" * } * } * } * } */ // 创建ES客户端对象 RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("localhost", 9200, "http"))); // 定义索引名称 CreateIndexRequest request = new CreateIndexRequest("user"); // 添加aliases,对比上述结构来理解 String aliaseStr = "{\"user.aliases\":{}}"; Map aliases = JSONObject.parseObject(aliaseStr, Map.class); // 添加mappings,对比上述结构来理解 String mappingStr = "{\"properties\":{\"name\":{\"type\":\"text\",\"fields\":{\"keyword\":{\"type\":\"keyword\"}}},\"sex\":{\"type\":\"keyword\"},\"age\":{\"type\":\"integer\"}}}"; Map mappings = JSONObject.parseObject(mappingStr, Map.class); // 添加settings,对比上述结构来理解 String settingStr = "{\"index\":{\"number_of_shards\":\"9\",\"number_of_replicas\":\"2\"}}"; Map settings = JSONObject.parseObject(settingStr, Map.class); // 添加数据 request.aliases(aliases); request.mapping(mappings); request.settings(settings); // 发送请求到ES CreateIndexResponse response = client.indices().create(request, RequestOptions.DEFAULT); // 处理响应结果 System.out.println("添加索引是否成功:" + response.isAcknowledged()); // 关闭ES客户端对象 client.close(); }
void getIndexInfo() throws Exception {
// 创建ES客户端对象
RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("localhost", 9200, "http")));
// 定义索引名称
GetIndexRequest request = new GetIndexRequest("user");
// 发送请求到ES
GetIndexResponse response = client.indices().get(request, RequestOptions.DEFAULT);
// 处理响应结果
System.out.println("aliases:" + response.getAliases());
System.out.println("mappings:" + response.getMappings());
System.out.println("settings:" + response.getSettings());
// 关闭ES客户端对象
client.close();
}
void existIndex() throws Exception {
// 1、创建ES客户端对象
RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("localhost", 9200, "http")));
// 2、定义请求对象
// user是索引名称
GetIndexRequest request = new GetIndexRequest("user");
// 3、发送请求到ES
boolean exist = client.indices().exists(request, RequestOptions.DEFAULT);
// 4、处理响应结果
System.out.println("索引存在于ES:" + exist);
// 5、关闭ES客户端对象
client.close();
}
void deleteIndex() throws Exception {
// 创建ES客户端对象
RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("localhost", 9200, "http")));
// 定义索引名称
DeleteIndexRequest request = new DeleteIndexRequest("user");
// 发送请求到ES
AcknowledgedResponse response = client.indices().delete(request, RequestOptions.DEFAULT);
// 处理响应结果
System.out.println("删除是否成功:" + response.isAcknowledged());
// 关闭ES客户端对象
client.close();
}
void insertDataToIndex() throws Exception { // 1、创建ES客户端对象 RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("localhost", 9200, "http"))); // 2、创建请求对象 User user = new User(); user.setName("张三"); user.setSex("男"); user.setAge(22); // 定义请求对象 IndexRequest request = new IndexRequest("user"); // 设置文档id request.id("1000"); // 将json格式字符串放在请求中 request.source(JSONObject.toJSONString(user), XContentType.JSON); // 3、发送请求到ES IndexResponse response = client.index(request, RequestOptions.DEFAULT); // 4、处理响应结果 System.out.println("数据插入结果:" + response.getResult()); // 5、关闭ES客户端对象 client.close(); }
void updateDataFromIndex() throws Exception { // 1、创建ES客户端对象 RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("localhost", 9200, "http"))); // 2、定义请求对象 User user = new User(); user.setName("小美"); user.setAge(20); UpdateRequest request = new UpdateRequest(); request.index("user").id("1000"); // 拓展:局部更新也可以这样写:request.doc(XContentType.JSON, "name", "小美", "age", 20);,其中"name"和"age"是User对象中的字段名称,而"小美"和20是对应的字段值 request.doc(JSONObject.toJSONString(user), XContentType.JSON); // 同步更新,可以根据需要开启 // request.setRefreshPolicy(WriteRequest.RefreshPolicy.WAIT_UNTIL); // 3、发送请求到ES UpdateResponse response = client.update(request, RequestOptions.DEFAULT); // 4、处理响应结果 System.out.println("数据更新结果:" + response.getResult()); // 5、关闭ES客户端对象 client.close(); }
void getDataById() throws Exception { // 1、创建ES客户端对象 RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("localhost", 9200, "http"))); // 2、定义请求对象 GetRequest request = new GetRequest("user"); request.id("1000"); // 只查询特定字段,在下面fields字段值中填写索引属性名称,中间用,分隔;注意:如果需要查询所有字段,则不设置该项 // String fields = "name"; // if (fields != null){ // request.fetchSourceContext(new FetchSourceContext(true,fields.split(","), Strings.EMPTY_ARRAY)); // } // 3、发送请求到ES GetResponse response = client.get(request, RequestOptions.DEFAULT); // 4、处理响应结果 System.out.println("查询结果:" + response.getSourceAsString()); // 5、关闭ES客户端对象 client.close(); }
void deleteDataById() throws Exception {
// 1、创建ES客户端对象
RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("localhost", 9200, "http")));
// 2、定义请求对象
DeleteRequest request = new DeleteRequest("user");
request.id("1000");
// 3、发送请求到ES
DeleteResponse response = client.delete(request, RequestOptions.DEFAULT);
// 4、处理响应结果
System.out.println("删除是否成功:" + response.getResult());
// 5、关闭ES客户端对象
client.close();
}
void deleteDataByQuery() throws IOException {
// 1、创建ES客户端对象
RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("localhost", 9200, "http")));
// 2、定义请求对象
DeleteByQueryRequest request = new DeleteByQueryRequest("user");
request.setQuery(QueryBuilders.matchAllQuery());
// 3、发送请求到ES
BulkByScrollResponse response = client.deleteByQuery(request, RequestOptions.DEFAULT);
// 4、处理响应结果
System.out.println("删除失败结果:" + response.getBulkFailures());
// 5、关闭ES客户端对象
client.close();
}
void batchInsertDataToIndex() throws Exception { // 1、创建ES客户端对象 RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("localhost", 9200, "http"))); // 2、定义请求对象 // 准备测试数据 List<User> userList = new ArrayList<>(10); for (int i = 0; i < 10; i++) { User user = new User(); user.setName(i % 2 == 0 ? "张三" + i : "小美" + i); user.setSex(i % 2 == 0 ? "男" : "女"); user.setAge(22 + i); userList.add(user); } BulkRequest bulkRequest = new BulkRequest(); // 准备批量插入的数据 userList.forEach(user -> { // 设置请求对象 IndexRequest request = new IndexRequest("user"); // 文档id request.id("10000" + user.getAge()); // 将json格式字符串放在请求中 // 下面这种写法也可以写成:request.source(XContentType.JSON, "name", "张三", "age", "男", "age", 22);,其中"name"、"age"、 "age"是User对象中的字段名,而这些字段名称后面的值就是对应的值 request.source(JSONObject.toJSONString(user), XContentType.JSON); // 将request添加到批量处理请求中 bulkRequest.add(request); }); // 3、发送请求到ES BulkResponse response = client.bulk(bulkRequest, RequestOptions.DEFAULT); // 4、处理响应结果 System.out.println("批量插入是否失败:" + response.hasFailures()); // 4.1、插入详细信息 for (BulkItemResponse itemResponse : response) { BulkItemResponse.Failure failure = itemResponse.getFailure(); if (failure == null) { System.out.println("插入成功的文档id:" + itemResponse.getId()); } else { System.out.println("插入失败的文档id:" + itemResponse.getId()); } } // 5、关闭ES客户端对象 client.close(); }
void batchDeleteDataFromIndex() throws Exception { // 1、创建ES客户端对象 RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("localhost", 9200, "http"))); // 2、定义请求对象 // 准备测试数据(只用到了age来生成文档id,但是为了和上面的批量插入应和,所以需要这样做) List<User> userList = new ArrayList<>(10); for (int i = 0; i < 10; i++) { User user = new User(); user.setName(i % 2 == 0 ? "张三" + i : "小美" + i); user.setSex(i % 2 == 0 ? "男" : "女"); user.setAge(22 + i); userList.add(user); } BulkRequest bulkRequest = new BulkRequest(); // 准备批量插入的数据 userList.forEach(user -> { // 设置请求对象 DeleteRequest request = new DeleteRequest("user"); // 文档id request.id("10000" + user.getAge()); // 将request添加到批量处理请求中 bulkRequest.add(request); }); // 3、发送请求到ES BulkResponse response = client.bulk(bulkRequest, RequestOptions.DEFAULT); // 4、处理响应结果 System.out.println("批量删除是否失败:" + response.hasFailures()); // 4.1、删除详细信息 for (BulkItemResponse itemResponse : response) { BulkItemResponse.Failure failure = itemResponse.getFailure(); if (failure == null) { System.out.println("删除成功的文档id:" + itemResponse.getId()); } else { System.out.println("删除失败的文档id:" + itemResponse.getId()); } } // 5、关闭ES客户端对象 client.close(); }
void advancedQueryFromAllData() throws Exception { // 1、创建ES客户端对象 RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("localhost", 9200, "http"))); // 2、定义请求对象 SearchRequest request = new SearchRequest(); request.indices("user"); // 指定检索条件 SearchSourceBuilder builder = new SearchSourceBuilder(); // 用来查询索引中全部的数据 builder.query(QueryBuilders.matchAllQuery()); request.source(builder); // 3、发送请求到ES SearchResponse response = client.search(request, RequestOptions.DEFAULT); // 4、处理响应结果 for (SearchHit hit : response.getHits().getHits()) { User user = JSONObject.parseObject(hit.getSourceAsString(), User.class); System.out.println("姓名:" + user.getName() + ";性别:" + user.getSex() + ";年龄:" + user.getAge()); } // 5、关闭ES客户端对象 client.close(); }
void advancedQueryByTerm() throws Exception { // 1、创建ES客户端对象 RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("localhost", 9200, "http"))); // 2、定义请求对象 SearchRequest request = new SearchRequest(); request.indices("user"); // 指定检索条件 SearchSourceBuilder builder = new SearchSourceBuilder(); // 用来查询sex是男的数据 builder.query(QueryBuilders.termQuery("sex", "男")); request.source(builder); // 3、发送请求到ES SearchResponse response = client.search(request, RequestOptions.DEFAULT); // 4、处理响应结果 for (SearchHit hit : response.getHits().getHits()) { User user = JSONObject.parseObject(hit.getSourceAsString(), User.class); System.out.println("姓名:" + user.getName() + ";性别:" + user.getSex() + ";年龄:" + user.getAge()); } // 5、关闭ES客户端对象 client.close(); }
void advancedQueryByPage() throws Exception { // 1、创建ES客户端对象 RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("localhost", 9200, "http"))); // 2、定义请求对象 SearchRequest request = new SearchRequest(); request.indices("user"); // 指定检索条件 SearchSourceBuilder builder = new SearchSourceBuilder(); // 分页查询数据,本次测试只查询前5条 builder.query(QueryBuilders.matchAllQuery()); int currentPage = 1; int pageSize = 5; int from = (currentPage - 1) * pageSize; builder.from(from); builder.size(pageSize); request.source(builder); // 3、发送请求到ES SearchResponse response = client.search(request, RequestOptions.DEFAULT); // 4、处理响应结果 for (SearchHit hit : response.getHits().getHits()) { User user = JSONObject.parseObject(hit.getSourceAsString(), User.class); System.out.println("姓名:" + user.getName() + ";性别:" + user.getSex() + ";年龄:" + user.getAge()); } // 5、关闭ES客户端对象 client.close(); }
void advancedQueryBySort() throws Exception { // 1、创建ES客户端对象 RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("localhost", 9200, "http"))); // 2、定义请求对象 SearchRequest request = new SearchRequest(); request.indices("user"); // 指定检索条件 SearchSourceBuilder builder = new SearchSourceBuilder(); builder.query(QueryBuilders.matchAllQuery()); // 根据年龄做降序排序 builder.sort("age", SortOrder.DESC); request.source(builder); // 3、发送请求到ES SearchResponse response = client.search(request, RequestOptions.DEFAULT); // 4、处理响应结果 for (SearchHit hit : response.getHits().getHits()) { User user = JSONObject.parseObject(hit.getSourceAsString(), User.class); System.out.println("姓名:" + user.getName() + ";性别:" + user.getSex() + ";年龄:" + user.getAge()); } // 5、关闭ES客户端对象 client.close(); }
void advancedQueryBySource() throws Exception { // 1、创建ES客户端对象 RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("localhost", 9200, "http"))); // 2、定义请求对象 SearchRequest request = new SearchRequest(); request.indices("user"); // 指定检索条件 SearchSourceBuilder builder = new SearchSourceBuilder(); builder.query(QueryBuilders.matchAllQuery()); // 如果查询的属性很少,那就使用includes,而excludes设置为空数组 // 如果排序的属性很少,那就使用excludes,而includes设置为空数组 String[] includes = {"name", "age"}; String[] excludes = {}; builder.fetchSource(includes, excludes); request.source(builder); // 3、发送请求到ES SearchResponse response = client.search(request, RequestOptions.DEFAULT); // 4、处理响应结果 for (SearchHit hit : response.getHits().getHits()) { User user = JSONObject.parseObject(hit.getSourceAsString(), User.class); System.out.println("姓名:" + user.getName() + ";性别:" + user.getSex() + ";年龄:" + user.getAge()); } // 5、关闭ES客户端对象 client.close(); }
void advancedQueryByShould() throws Exception { // 1、创建ES客户端对象 RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("localhost", 9200, "http"))); // 2、定义请求对象 SearchRequest request = new SearchRequest(); request.indices("user"); // 指定检索条件 SearchSourceBuilder builder = new SearchSourceBuilder(); BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery(); boolQueryBuilder.should(QueryBuilders.matchQuery("age", 30)); // 查询中boost默认是1,写成10可以增大score比分 boolQueryBuilder.should(QueryBuilders.matchQuery("sex", "女").boost(10)); builder.query(boolQueryBuilder); request.source(builder); // 3、发送请求到ES SearchResponse response = client.search(request, RequestOptions.DEFAULT); // 4、处理响应结果 for (SearchHit hit : response.getHits().getHits()) { User user = JSONObject.parseObject(hit.getSourceAsString(), User.class); System.out.println("姓名:" + user.getName() + ";性别:" + user.getSex() + ";年龄:" + user.getAge()); } // 5、关闭ES客户端对象 client.close(); }
void advancedQueryByFilter() throws Exception { // 1、创建ES客户端对象 RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("localhost", 9200, "http"))); // 2、定义请求对象 SearchRequest request = new SearchRequest(); request.indices("user"); // 指定检索条件 SearchSourceBuilder builder = new SearchSourceBuilder(); BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery(); // 查询年龄大于等于26,小于等于29的结果 boolQueryBuilder.filter(QueryBuilders.rangeQuery("age").gte(26).lte(29)); builder.query(boolQueryBuilder); request.source(builder); // 3、发送请求到ES SearchResponse response = client.search(request, RequestOptions.DEFAULT); // 4、处理响应结果 for (SearchHit hit : response.getHits().getHits()) { User user = JSONObject.parseObject(hit.getSourceAsString(), User.class); System.out.println("姓名:" + user.getName() + ";性别:" + user.getSex() + ";年龄:" + user.getAge()); } // 5、关闭ES客户端对象 client.close(); }
void advancedQueryByLike() throws Exception { // 1、创建ES客户端对象 RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("localhost", 9200, "http"))); // 2、定义请求对象 SearchRequest request = new SearchRequest(); request.indices("user"); // 指定检索条件 SearchSourceBuilder builder = new SearchSourceBuilder(); // 和分词无关,这就是和mysql中like类似的做法 // 查询名称中包含“张三”的数据,或者比“张三”多一个字符的数据,这是通过Fuzziness.ONE来控制的,比如“张三1”是可以出现的,但是“张三12”是无法出现的,这是因为他比张三多了两个字符;除了“Fuzziness.ONE”之外,还可以是“Fuzziness.TWO”等 builder.query(QueryBuilders.fuzzyQuery("name.keyword", "张三").fuzziness(Fuzziness.ONE)); request.source(builder); // 3、发送请求到ES SearchResponse response = client.search(request, RequestOptions.DEFAULT); // 4、处理响应结果 for (SearchHit hit : response.getHits().getHits()) { User user = JSONObject.parseObject(hit.getSourceAsString(), User.class); System.out.println("姓名:" + user.getName() + ";性别:" + user.getSex() + ";年龄:" + user.getAge()); } // 5、关闭ES客户端对象 client.close(); }
void advancedQueryByHighLight() throws Exception { // 1、创建ES客户端对象 RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("localhost", 9200, "http"))); // 2、定义请求对象 SearchRequest request = new SearchRequest(); request.indices("user"); // 指定检索条件 SearchSourceBuilder builder = new SearchSourceBuilder(); // 设置查询条件 builder.query(QueryBuilders.matchPhraseQuery("name", "张三")); // 构建高亮查询对象 HighlightBuilder highlightBuilder = new HighlightBuilder(); // 前置标签 highlightBuilder.preTags("<b style='color:red'>"); // 后置标签 highlightBuilder.postTags("</b>"); // 添加高亮的属性名称 highlightBuilder.field("name"); builder.highlighter(highlightBuilder); request.source(builder); // 3、发送请求到ES SearchResponse response = client.search(request, RequestOptions.DEFAULT); // 4、处理响应结果 SearchHit[] hits = response.getHits().getHits(); for (SearchHit hit : hits) { Map<String, HighlightField> map = hit.getHighlightFields(); HighlightField highlightField = map.get("name"); System.out.println("高亮名称:" + highlightField.getFragments()[0].string()); } // 5、关闭ES客户端对象 client.close(); }
void advancedQueryByMaxValueAggregation() throws Exception { // 1、创建ES客户端对象 RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("localhost", 9200, "http"))); // 2、定义请求对象 SearchRequest request = new SearchRequest(); request.indices("user"); // 指定检索条件 SearchSourceBuilder builder = new SearchSourceBuilder(); // 获取最大年龄 AggregationBuilder aggregationBuilder = AggregationBuilders.max("maxAge").field("age"); builder.aggregation(aggregationBuilder); // 设置size为0,不查询具体数据,只查询聚合结果 builder.size(0); request.source(builder); // 3、发送请求到ES SearchResponse response = client.search(request, RequestOptions.DEFAULT); // 4、处理响应结果 Aggregations aggregations = response.getAggregations(); ParsedMax maxAge = aggregations.get("maxAge"); System.out.println("最大年龄:" + maxAge.getValue()); // 5、关闭ES客户端对象 client.close(); }
void advancedQueryByGroupAggregation() throws Exception { // 1、创建ES客户端对象 RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("localhost", 9200, "http"))); // 2、定义请求对象 SearchRequest request = new SearchRequest(); request.indices("user"); // 指定检索条件 SearchSourceBuilder builder = new SearchSourceBuilder(); // 按照性别分组,聚合操作要求和分词操作无关,由于sex在默认添加的时候是text类型,因为需要设置为keyword类型 AggregationBuilder aggregationBuilder = AggregationBuilders.terms("termsSex").field("sex.keyword"); builder.aggregation(aggregationBuilder); // 设置size为0,不查询具体数据,只查询聚合结果 builder.size(0); request.source(builder); // 3、发送请求到ES SearchResponse response = client.search(request, RequestOptions.DEFAULT); // 4、处理响应结果 Aggregations aggregations = response.getAggregations(); // 至于使用ParsedStringTerms、ParsedLongTerms、ParsedMax、ParsedNested、ParsedAvg……是由聚合要求和聚合字段类型确定的,比如本次要求是分组,并且聚合字段是sex,那就是String类型,所以使用ParsedStringTerms ParsedStringTerms termsSex = aggregations.get("termsSex"); for (Terms.Bucket bucket : termsSex.getBuckets()) { System.out.println("性别:" + bucket.getKeyAsString() + ";数量:" + bucket.getDocCount()); } // 5、关闭ES客户端对象 client.close(); }
void count() throws Exception { // 1、创建ES客户端对象 RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("localhost", 9200, "http"))); // 2、定义请求对象 CountRequest request = new CountRequest(); request.indices("user"); // 指定检索条件 request.query(QueryBuilders.matchAllQuery()); // 如果索引不存在,不会报错 request.indicesOptions(IndicesOptions.fromOptions(true, true, false, false)); // 3、发送请求到ES CountResponse response = client.count(request, RequestOptions.DEFAULT); // 4、处理响应结果 System.out.println("数据总量:" + response.getCount()); // 5、关闭ES客户端对象 client.close(); }
void scrollQuery() throws Exception { // 1、创建ES客户端对象 RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("localhost", 9200, "http"))); // 2、定义请求对象 // 假设用户想获取第10页数据,其中每页20条 int totalPage = 10; int size = 20; SearchRequest searchRequest = new SearchRequest("user"); // 指定检索条件 SearchSourceBuilder builder = new SearchSourceBuilder(); searchRequest.source(builder.query(QueryBuilders.matchAllQuery()).size(size)); String scrollId = null; // 3、发送请求到ES SearchResponse scrollResponce = null; // 设置游标id存活时间 Scroll scroll = new Scroll(TimeValue.timeValueMinutes(2)); // 记录所有游标id List<String> scrollIds = new ArrayList<>(); for (int i = 0; i < totalPage; i++) { try { // 首次检索 if (i == 0) { //记录游标id searchRequest.scroll(scroll); // 首次查询需要指定索引名称和查询条件 SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT); // 下一次搜索要用到该游标id scrollId = response.getScrollId(); // 记录所有游标id scrollIds.add(scrollId); } // 非首次检索 else { // 不需要在使用其他条件,也不需要指定索引名称,只需要使用执行游标id存活时间和上次游标id即可,毕竟信息都在上次游标id里面呢 SearchScrollRequest searchScrollRequest = new SearchScrollRequest(scrollId); searchScrollRequest.scroll(scroll); scrollResponce = client.scroll(searchScrollRequest, RequestOptions.DEFAULT); // 下一次搜索要用到该游标id scrollId = scrollResponce.getScrollId(); // 记录所有游标id scrollIds.add(scrollId); } } catch (Exception e) { e.printStackTrace(); } } //清除游标id ClearScrollRequest clearScrollRequest = new ClearScrollRequest(); clearScrollRequest.scrollIds(scrollIds); try { client.clearScroll(clearScrollRequest, RequestOptions.DEFAULT); } catch (IOException e) { System.out.println("清除滚动查询游标id失败"); e.printStackTrace(); } // 4、处理响应结果 System.out.println("滚动查询返回数据:" + scrollResponce); // 5、关闭ES客户端对象 client.close(); }
void existById() throws Exception { // 1、创建ES客户端对象 RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("localhost", 9200, "http"))); // 2、定义请求对象 // user是索引名称,1000是文档id GetRequest request = new GetRequest("user", "1000"); // 不获取返回的_source的上下文 request.fetchSourceContext(new FetchSourceContext(false)); request.storedFields("_none_"); // 3、发送请求到ES boolean exist = client.exists(request, RequestOptions.DEFAULT); // 4、处理响应结果 System.out.println("文档存在于ES:" + exist); // 5、关闭ES客户端对象 client.close(); }
void multiQueryById() throws Exception { // 1、创建ES客户端对象 RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("localhost", 9200, "http"))); // 2、定义请求对象 MultiGetRequest request = new MultiGetRequest(); // user是索引名称,1000和2000都是文档id request.add("user", "1000"); request.add("user", "2000"); // 3、发送请求到ES MultiGetResponse response = client.mget(request, RequestOptions.DEFAULT); // 4、处理响应结果 List<String> existIdList = new ArrayList<>(); for (MultiGetItemResponse itemResponse : response) { MultiGetResponse.Failure failure = itemResponse.getFailure(); GetResponse getResponse = itemResponse.getResponse(); if (failure == null) { boolean exists = getResponse.isExists(); String id = getResponse.getId(); if (exists) { existIdList.add(id); } } else { failure.getFailure().printStackTrace(); } } System.out.println("数据存在于ES的文档id:" + existIdList); // 5、关闭ES客户端对象 client.close(); }
void printClusterNameAndStatus() throws Exception { // 1、创建ES客户端对象 RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("localhost", 9200, "http"))); // 2、定义请求对象 ClusterHealthRequest request = new ClusterHealthRequest(); // 3、发送请求到ES ClusterHealthResponse response = client.cluster().health(request, RequestOptions.DEFAULT); // 4、获取健康状况 ClusterHealthStatus status = response.getStatus(); // 5、打印集群名称 System.out.println("集群名称:" + response.getClusterName()); // 6、打印集群状态 System.out.println("集群健康状态:" + status.name()); // 7、关闭ES客户端对象 client.close(); }
void printIndexInfo() throws Exception { // 1、创建ES客户端对象 RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("localhost", 9200, "http"))); // 2、发送请求到ES Response response = client.getLowLevelClient().performRequest(new Request("GET", "/_cat/indices")); // 3、数据处理 HttpEntity entity = response.getEntity(); String responseStr = EntityUtils.toString(entity, StandardCharsets.UTF_8); // 4、数据分解 String[] indexInfoArr = responseStr.split("\n"); for (String indexInfo : indexInfoArr) { // 4.1、索引信息输出 String[] infoArr = indexInfo.split("\\s+"); String status = infoArr[0]; String open = infoArr[1]; String name = infoArr[2]; String id = infoArr[3]; String mainShardNum = infoArr[4]; String viceShardNum = infoArr[5]; String docNum = infoArr[6]; String deletedDocNum = infoArr[7]; String allShardSize = infoArr[8]; String mainShardSize = infoArr[9]; System.out.println("》》》》》》》》索引信息》》》》》》》》"); System.out.println("名称:" + name); System.out.println("id:" + id); System.out.println("状态:" + status); System.out.println("是否开放:" + open); System.out.println("主分片数量:" + mainShardNum); System.out.println("副本分片数量:" + viceShardNum); System.out.println("Lucene文档数量:" + docNum); System.out.println("被删除文档数量:" + deletedDocNum); System.out.println("所有分片大小:" + allShardSize); System.out.println("主分片大小:" + mainShardSize); } // 6、关闭ES客户端对象 client.close(); }
// 方法1
CountRequest request = new CountRequest("index1", "index2");
// 方法2
CountRequest request = new CountRequest();
request.indices("index1", "index2");
// request可以是CountRequest、SearchRequest对象
// 注意:如果不设置下列参数,在查询的时候将会出现索引不存在错误
request.indicesOptions(IndicesOptions.fromOptions(true, true, false, false));
import org.apache.http.HttpHost; import org.elasticsearch.client.RestClient; import org.elasticsearch.client.RestHighLevelClient; import org.springframework.boot.test.context.SpringBootTest; @SpringBootTest class ESTestApplicationTests { // ES客户端对象 private static RestHighLevelClient client; static { // 创建ES客户端对象 // 1、单机版 // 1.1、无密码 client = new RestHighLevelClient(RestClient.builder(new HttpHost("localhost", 9200, "http"))); // 1.2有密码 // RestClientBuilder builder = RestClient.builder(new HttpHost("192.168.56.10", 9200, "http")); // // 设置用户名和密码 // String username = "elastic"; // String password = "123456"; // CredentialsProvider credentialsProvider = new BasicCredentialsProvider(); // credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(username, password)); // builder.setHttpClientConfigCallback(f -> f.setDefaultCredentialsProvider(credentialsProvider)); // client = new RestHighLevelClient(builder); // 2、集群版 // 1.2、无密码 // client = new RestHighLevelClient( // RestClient.builder( // new HttpHost("localhost", 9201, "http"), // new HttpHost("localhost", 9202, "http"), // new HttpHost("localhost", 9203, "http") // ) // ); // 2.2有密码 // RestClientBuilder builder = RestClient.builder( // new HttpHost("192.168.56.10", 9201, "http"), // new HttpHost("192.168.56.10", 9202, "http"), // new HttpHost("192.168.56.10", 9203, "http") // ); // // 设置用户名和密码 // String username = "elastic"; // String password = "123456"; // CredentialsProvider credentialsProvider = new BasicCredentialsProvider(); // credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(username, password)); // builder.setHttpClientConfigCallback(f -> f.setDefaultCredentialsProvider(credentialsProvider)); // client = new RestHighLevelClient(builder); } }
public class ESSaveServiceImpl implements ESSaveService { @Resource private RestHighLevelClient client; @Override public Boolean productUp(List<SkuEsModel> list) throws IOException { // 创建批量处理请求 BulkRequest bulkRequest = new BulkRequest(); // 将需要处理的请求添加到批量处理请求中 list.forEach(model -> { // 索引名称为product IndexRequest request = new IndexRequest(ESConstant.PRODUCT_INDEX); // 文档id,要求为String类型 // The id of the indexed document. If not set, will be automatically generated. request.id(model.getSkuId().toString()); // 将需要传输的数据转换为json格式字符串 String jsonString = JSONObject.toJSONString(model); // 将json格式字符串放在请求中 request.source(jsonString, XContentType.JSON); // 将request添加到批量处理请求中 bulkRequest.add(request); }); // 发送请求到es进行批量处理 BulkResponse bulk = client.bulk(bulkRequest, ElasticsearchConfig.COMMON_OPTIONS); // 返回批量处理是否成功 return bulk.hasFailures(); } }
PUT gulimall_product { "mappings": { "properties": { "skuId": { "type": "long" }, "spuId": { "type": "keyword" }, "skuTitle": { "type": "text", "analyzer": "ik_smart" }, "skuPrice": { "type": "double" }, "skuImg": { "type": "keyword" }, "saleCount": { "type": "long" }, "hasStock": { "type": "boolean" }, "hotScore": { "type": "long" }, "brandId": { "type": "long" }, "catalogId": { "type": "long" }, "brandName": { "type": "keyword" }, "brandImg": { "type": "keyword" }, "catalogName": { "type": "keyword" }, "attrs": { "type": "nested", "properties": { "attrId": { "type": "long" }, "attrName": { "type": "keyword" }, "attrValue": { "type": "keyword" } } } } } }
public class ESSearchServiceImpl implements ESSearchService { @Resource private RestHighLevelClient client; @Resource private ProductFeignService productFeignService; @Override public SearchResult search(SearchParam param) { // 返回数据 SearchResult result = new SearchResult(); // 1、创建检索请求 SearchRequest searchRequest = buildSearchRequest(param); try { // 2、执行检索,获取响应数据 SearchResponse response = client.search(searchRequest, ElasticsearchConfig.COMMON_OPTIONS); // 3、分析响应数据,将响应数据封装成我们想要的格式 result = buildSearchResult(response, param); } catch (IOException e) { e.printStackTrace(); } return result; } /** * 构建检索请求 * * @return */ private SearchRequest buildSearchRequest(SearchParam param) { // 指定Query DSL,即检索条件 SearchSourceBuilder sourceBuilder = new SearchSourceBuilder(); // **************************构建查询条件start*********************** BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery(); if (StringUtils.isNotEmpty(param.getKeyword())) { boolQueryBuilder.must(QueryBuilders.matchQuery("skuTitle", param.getKeyword())); } if (ObjectUtils.allNotNull(param.getCatalog3Id())) { boolQueryBuilder.filter(QueryBuilders.termQuery("catalogId", param.getCatalog3Id())); } if (ObjectUtils.allNotNull(param.getBrandId()) && param.getBrandId().size() > 0) { boolQueryBuilder.filter(QueryBuilders.termsQuery("brandId", param.getBrandId())); } if (ObjectUtils.allNotNull(param.getAttrs()) && param.getAttrs().size() > 0) { param.getAttrs().forEach(attr -> { BoolQueryBuilder boolQuery = QueryBuilders.boolQuery(); // attrs=1_安卓:苹果:塞班&attrs=2_5寸:6寸 String[] s1 = attr.split("_"); String[] s2 = s1[1].split(":"); boolQuery.must(QueryBuilders.termQuery("attrs.attrId", s1[0])); boolQuery.must(QueryBuilders.termsQuery("attrs.attrValue", s2)); // ScoreMode.None表示不参与评分 boolQueryBuilder.filter(QueryBuilders.nestedQuery("attrs", boolQuery, ScoreMode.None)); }); } if (ObjectUtils.allNotNull(param.getHasStock())) { boolQueryBuilder.filter(QueryBuilders.termQuery("hasStock", param.getHasStock() == 1)); } if (StringUtils.isNotEmpty(param.getSkuPrice())) { RangeQueryBuilder rangeQuery = QueryBuilders.rangeQuery("skuPrice"); String[] s = param.getSkuPrice().split("_"); if (s.length == 2 && StringUtils.isNotEmpty(s[0])) { rangeQuery.gte(s[0]).lte(s[1]); } else if (s.length == 2 && param.getSkuPrice().startsWith("_")) { // 由于"_8000"分割之后会出现["", "8000"]这种情况,所以我们这样做 rangeQuery.lte(s[1]); } else if (s.length == 1 && param.getSkuPrice().endsWith("_")) { rangeQuery.gte(s[0]); } boolQueryBuilder.filter(rangeQuery); } sourceBuilder.query(boolQueryBuilder); // **************************构建查询条件end*********************** // **************************构建排序条件start*********************** /* * 排序条件 * sort=saleCount_asc/desc---》销量 * sort=skuPrice_asc/desc---》价格 * sort=hotScore_asc/desc---》热度评分 */ if (StringUtils.isNotEmpty(param.getSort())) { String[] s = param.getSort().split("_"); SortOrder order = "asc".equalsIgnoreCase(s[1]) ? SortOrder.ASC : SortOrder.DESC; sourceBuilder.sort(s[0], order); } // **************************构建排序条件end*********************** // **************************构建分页条件start*********************** int start = (param.getPageNum() - 1) * ESConstant.PAGE_SIZE; sourceBuilder.from(start).size(ESConstant.PAGE_SIZE); // **************************构建分页条件end*********************** // **************************构建高亮条件start*********************** if (StringUtils.isNotEmpty(param.getKeyword())) { HighlightBuilder builder = new HighlightBuilder(); builder.preTags("<b style='color:red'>"); builder.postTags("</b>"); builder.field("skuTitle"); sourceBuilder.highlighter(builder); } // **************************构建高亮条件end*********************** // **************************构建聚合条件start*********************** // 创建聚合 TermsAggregationBuilder brandAgg = AggregationBuilders.terms("brand_agg") .field("brandId").size(32); // 添加子聚合 brandAgg.subAggregation(AggregationBuilders.terms("brand_name_agg") .field("brandName").size(1)); brandAgg.subAggregation(AggregationBuilders.terms("brand_img_agg") .field("brandImg").size(1)); // 创建聚合 TermsAggregationBuilder catalogAgg = AggregationBuilders.terms("catalog_agg") .field("catalogId").size(14); // 添加子聚合 catalogAgg.subAggregation(AggregationBuilders.terms("catalog_name_agg") .field("catalogName").size(1)); // 创建聚合 NestedAggregationBuilder attrAgg = AggregationBuilders.nested("attr_agg", "attrs"); // 添加子聚合 TermsAggregationBuilder attrIdAgg = AggregationBuilders.terms("attr_id_agg") .field("attrs.attrId").size(14); // 添加孙子聚合 attrIdAgg.subAggregation(AggregationBuilders.terms("attr_name_agg").field("attrs.attrName").size(1)); attrIdAgg.subAggregation(AggregationBuilders.terms("attr_value_agg").field("attrs.attrValue").size(12)); attrAgg.subAggregation(attrIdAgg); // 将聚合添加到请求中 sourceBuilder.aggregation(brandAgg); sourceBuilder.aggregation(catalogAgg); sourceBuilder.aggregation(attrAgg); // **************************构建聚合条件end*********************** // 创建检索请求:首先要指定被检索的索引,然后添加检索条件 SearchRequest searchRequest = new SearchRequest(new String[]{ESConstant.PRODUCT_INDEX}, sourceBuilder); return searchRequest; } /** * 构建响应结果 * * @return */ private SearchResult buildSearchResult(SearchResponse response, SearchParam param) { // 总返回结果 SearchResult result = new SearchResult(); // 获取es返回的结果 SearchHits hits = response.getHits(); // 1、所有返回的商品信息 List<SkuEsModel> products = new ArrayList<>(); // 获得检索信息 SearchHit[] searchHits = hits.getHits(); if (searchHits != null && searchHits.length > 0) { // 将hits中的hits中的值放在对象中 for (SearchHit hit : searchHits) { String str = hit.getSourceAsString(); // 普通类型可以直接这样写,复杂类型需要用new TypeReference<类型>(){}来完成,例如List<XXX>就是复杂类型 SkuEsModel skuEsModel = JSONObject.parseObject(str, SkuEsModel.class); // 如果有全文检索关键字,那就需要使用高亮显示 if (StringUtils.isNotEmpty(param.getKeyword())) { // 以下结果是debug返回值response,分析控制台中的response中的internalResponse---》hits---》hits得出来的 Map<String, HighlightField> highlightFields = hit.getHighlightFields(); HighlightField highlightField = highlightFields.get("skuTitle"); String skuTitle = highlightField.getFragments()[0].string(); skuEsModel.setSkuTitle(skuTitle); } products.add(skuEsModel); } } // 将商品信息放在总返回结果中 result.setProducts(products); // 获得聚合信息 // 注意:聚合中用到的ParsedLongTerms、ParsedStringTerms、ParsedNested类型来自于debug返回值response,通过查看控制台response中的internalResponse---》aggregations得出返回值类型 Aggregations aggregations = response.getAggregations(); // 2、检索出来的所有品牌信息 List<SearchResult.BrandVo> brands = new ArrayList<>(); // 分析聚合信息 ParsedLongTerms brandAgg = aggregations.get("brand_agg"); // 判断聚合信息是否为空 if (ObjectUtils.allNotNull(brandAgg) && brandAgg.getBuckets().size() > 0) { for (Terms.Bucket bucket : brandAgg.getBuckets()) { // 返回对象 SearchResult.BrandVo brandVo = new SearchResult.BrandVo(); // 放品牌id String brandId = bucket.getKeyAsString(); brandVo.setBrandId(Long.parseLong(brandId)); // 放品牌图片 ParsedStringTerms brandImgAgg = bucket.getAggregations().get("brand_img_agg"); brandVo.setBrandImg(brandImgAgg.getBuckets().get(0).getKeyAsString()); // 放品牌名称 ParsedStringTerms brandNameAgg = bucket.getAggregations().get("brand_name_agg"); brandVo.setBrandName(brandNameAgg.getBuckets().get(0).getKeyAsString()); // 将对象放入返回值 brands.add(brandVo); } } // 将聚合信息添加到总返回结果中 result.setBrands(brands); // 3、检索出来的所有分类信息 List<SearchResult.CatalogVo> catalogs = new ArrayList<>(); // 分析聚合信息 ParsedLongTerms catalogAgg = aggregations.get("catalog_agg"); // 判断聚合信息是否为空 if (ObjectUtils.allNotNull(catalogAgg) && catalogAgg.getBuckets().size() > 0) { for (Terms.Bucket bucket : catalogAgg.getBuckets()) { // 返回对象 SearchResult.CatalogVo catalogVo = new SearchResult.CatalogVo(); // 放分类id String catalogId = bucket.getKeyAsString(); catalogVo.setCatalogId(Long.parseLong(catalogId)); // 放分类名称 ParsedStringTerms catalogNameAgg = bucket.getAggregations().get("catalog_name_agg"); catalogVo.setCatalogName(catalogNameAgg.getBuckets().get(0).getKeyAsString()); // 将对象放入返回值 catalogs.add(catalogVo); } } // 将聚合信息添加到总返回结果中 result.setCatalogs(catalogs); // 4、所有涉及到的可以检索的属性信息 List<SearchResult.AttrVo> attrs = new ArrayList<>(); // 分析聚合信息 ParsedNested attrAgg = aggregations.get("attr_agg"); ParsedLongTerms attrIdAgg = attrAgg.getAggregations().get("attr_id_agg"); // 判断聚合信息是否为空 if (ObjectUtils.allNotNull(attrIdAgg) && attrIdAgg.getBuckets().size() > 0) { for (Terms.Bucket bucket : attrIdAgg.getBuckets()) { // 返回对象 SearchResult.AttrVo attrVo = new SearchResult.AttrVo(); // 放分类id String attrId = bucket.getKeyAsString(); attrVo.setAttrId(Long.parseLong(attrId)); // 放分类名称 ParsedStringTerms attrNameAgg = bucket.getAggregations().get("attr_name_agg"); attrVo.setAttrName(attrNameAgg.getBuckets().get(0).getKeyAsString()); // 放分类值 ParsedStringTerms attrValueAgg = bucket.getAggregations().get("attr_value_agg"); // 创建分类值列表 List<String> attrValue = new ArrayList<>(); for (Terms.Bucket bucket1 : attrValueAgg.getBuckets()) { attrValue.add(bucket1.getKeyAsString()); } // 放分类值列表 attrVo.setAttrValue(attrValue); // 将对象放入返回值 attrs.add(attrVo); } } // 将聚合信息添加到总返回结果中 result.setAttrs(attrs); // 5、总记录数 long total = hits.getTotalHits().value; result.setTotal(total); // 6、总页数 int totalPage = (int) total % ESConstant.PAGE_SIZE > 0 ? ((int) total / ESConstant.PAGE_SIZE + 1) : (int) total / ESConstant.PAGE_SIZE; result.setTotalPage(totalPage); // 7、当前页 result.setPageNum(param.getPageNum()); // 8、面包屑导航 // 处理属性面包屑导航 if (param.getAttrs() != null && param.getAttrs().size() > 0) { List<SearchResult.NavVo> navVos = param.getAttrs().stream().map(attr -> { SearchResult.NavVo navVo = new SearchResult.NavVo(); // attr就类似于attrs=1_安卓:苹果:塞班中的1_安卓:苹果:塞班 String[] s = attr.split("_"); // 将所有属性id依次放在属性id集合中,前端隐藏属性选择表的时候可以用 result.getAttrIds().add(Long.parseLong(s[0])); // 把navValue按照v1,v2……这种方式放在navVo返回值中 String[] values = s[1].split(":"); StringBuilder sb = new StringBuilder(); for (int i = 0; i < values.length; i++) { sb.append(values[i]); if (i < values.length - 1) { sb.append(","); } } navVo.setNavValue(sb.toString()); // 把navName放在navVo返回值中 R r = productFeignService.attrInfo(Long.parseLong(s[0])); if (r.getCode() == Constant.SUCCESS_CODE) { AttrRespVo attrRespVo = r.getData("attr", new TypeReference<AttrRespVo>() { }); navVo.setNavName(attrRespVo.getAttrName()); } else { navVo.setNavName(s[0]); } // 把link放在navVo返回值中 String link = getLinkByAttrs(param.get_requestURI(), param.get_queryString(), "attrs", attr); navVo.setLink(link); // 返回相应对象 return navVo; }).collect(Collectors.toList()); // 将面包屑导航集合放在返回结果中 result.setNavVos(navVos); } // 处理商标面包屑导航 if (param.getBrandId() != null && param.getBrandId().size() > 0) { // 获取面包屑导航集合 List<SearchResult.NavVo> navVos = result.getNavVos(); SearchResult.NavVo navVo = new SearchResult.NavVo(); navVo.setNavName("品牌"); // 从远程获取数据 R r = productFeignService.brandInfo(param.getBrandId()); // 判断获取远程数据是否成功 if (r.getCode() == Constant.SUCCESS_CODE) { // 获取远程数据 List<BrandVo> brandVos = r.getData("brand", new TypeReference<List<BrandVo>>() { }); // 用来存储商标名称,毕竟在设计之初可以多选,最后名称类似于"华为,Apple" StringBuilder sb = new StringBuilder(); // 去掉所有商标信息的地址 String link = null; // 所有商标id集合 List<Long> brandIds = new ArrayList<>(); for (int i = 0; i < brandVos.size(); i++) { sb.append(brandVos.get(i).getName()); if (i < brandVos.size() - 1) { sb.append(","); } brandIds.add(brandVos.get(i).getBrandId()); } link = getLinkByBrandId(param.get_requestURI(), param.get_queryString(), "brandId", brandIds); // 将经过遍历的值添加进去 navVo.setLink(link); navVo.setNavValue(sb.toString()); } else { // 获取远程数据出错,进行处理 navVo.setNavValue("首页"); navVo.setLink("http://gulimall.com"); } // 将商标信息添加到面包屑导航中 navVos.add(navVo); } // 最终返回给前端的数据 return result; } // 删除相关属性,然后获取链接 private String getLinkByAttrs(String requestUri, String queryString, String key, String value) { String encode = null; try { // 前端地址会把空格变成%20,而后端使用URLEncoder.encode()之后会把空格变成+,所以我们需要使用replaceAll替换操作,还有执行URLEncoder.encode()之后会将/转义,但是我不需要转义 // 注意:只能改变自己去适应前端变化,不能改变前端的地址信息,否则前端不能访问了怎么办? encode = URLEncoder.encode(value, "UTF-8").replaceAll("\\+", "%20").replaceAll("%2F","/"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } // 可能该属性是中间值或者最后一个值(前面还有值) queryString = queryString.replace("&" + key + "=" + encode, ""); // 可能该属性是第一个值,后面还有值 queryString = queryString.replace(key + "=" + encode + "&", ""); // 可能该属性是第一个值,后面没有值 queryString = queryString.replace(key + "=" + encode, ""); if (StringUtils.isNotEmpty(queryString)) { return "http://search.gulimall.com" + requestUri + "?" + queryString; } else { return "http://search.gulimall.com" + requestUri; } } // 删除所有品牌id,然后获取链接 private String getLinkByBrandId(String requestUri, String queryString, String key, List<Long> values) { // 把所有品牌id参数都去掉 for (Long value : values) { // 可能该属性是中间值或者最后一个值(前面还有值) queryString = queryString.replace("&" + key + "=" + value, ""); // 可能该属性是第一个值,后面还有值 queryString = queryString.replace(key + "=" + value + "&", ""); // 可能该属性是第一个值,后面没有值 queryString = queryString.replace(key + "=" + value, ""); } if (StringUtils.isNotEmpty(queryString)) { return "http://search.gulimall.com" + requestUri + "?" + queryString; } else { return "http://search.gulimall.com" + requestUri; } } }
请看 四、实战》1、批量插入》1.1、对应索引结构
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。