一、引入依赖
<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>
二、代码
1、添加索引结构到es
void addIndex() throws Exception {
RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("localhost", 9200, "http")));
CreateIndexRequest request = new CreateIndexRequest("user");
String aliaseStr = "{\"user.aliases\":{}}";
Map aliases = JSONObject.parseObject(aliaseStr, Map.class);
String mappingStr = "{\"properties\":{\"name\":{\"type\":\"text\",\"fields\":{\"keyword\":{\"type\":\"keyword\"}}},\"sex\":{\"type\":\"keyword\"},\"age\":{\"type\":\"integer\"}}}";
Map mappings = JSONObject.parseObject(mappingStr, Map.class);
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);
CreateIndexResponse response = client.indices().create(request, RequestOptions.DEFAULT);
System.out.println("添加索引是否成功:" + response.isAcknowledged());
client.close();
}
2、获取索引信息
void getIndexInfo() throws Exception {
RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("localhost", 9200, "http")));
GetIndexRequest request = new GetIndexRequest("user");
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());
client.close();
}
3、删除索引
void deleteIndex() throws Exception {
RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("localhost", 9200, "http")));
DeleteIndexRequest request = new DeleteIndexRequest("user");
AcknowledgedResponse response = client.indices().delete(request, RequestOptions.DEFAULT);
System.out.println("删除是否成功:" + response.isAcknowledged());
client.close();
}
4、添加数据到索引中
void insertDataToIndex() throws Exception {
RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("localhost", 9200, "http")));
User user = new User();
user.setName("张三");
user.setSex("男");
user.setAge(22);
IndexRequest request = new IndexRequest("user");
request.id("1000");
request.source(JSONObject.toJSONString(user), XContentType.JSON);
IndexResponse response = client.index(request, RequestOptions.DEFAULT);
System.out.println("数据插入结果:" + response.getResult());
client.close();
}
5、局部更新索引中的数据
void updateDataFromIndex() throws Exception {
RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("localhost", 9200, "http")));
User user = new User();
user.setName("小美");
user.setAge(20);
UpdateRequest request = new UpdateRequest();
request.index("user").id("1000");
request.doc(JSONObject.toJSONString(user), XContentType.JSON);
UpdateResponse response = client.update(request, RequestOptions.DEFAULT);
System.out.println("数据更新结果:" + response.getResult());
client.close();
}
6、根据文档id查询索引中的数据
void getDataById() throws Exception {
RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("localhost", 9200, "http")));
GetRequest request = new GetRequest("user");
request.id("1000");
GetResponse response = client.get(request, RequestOptions.DEFAULT);
System.out.println("查询结果:" + response.getSourceAsString());
client.close();
}
7、根据文档id删除索引中的数据
void deleteDataById() throws Exception {
RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("localhost", 9200, "http")));
DeleteRequest request = new DeleteRequest("user");
request.id("1000");
DeleteResponse response = client.delete(request, RequestOptions.DEFAULT);
System.out.println("删除是否成功:" + response.getResult());
client.close();
}
8、根据查询条件删除索引中的数据
void deleteDataByQuery() throws IOException {
RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("localhost", 9200, "http")));
DeleteByQueryRequest request = new DeleteByQueryRequest("user");
request.setQuery(QueryBuilders.matchAllQuery());
BulkByScrollResponse response = client.deleteByQuery(request, RequestOptions.DEFAULT);
System.out.println("删除失败结果:" + response.getBulkFailures());
client.close();
}
9、批量插入数据到索引中
void batchInsertDataToIndex() throws Exception {
RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("localhost", 9200, "http")));
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");
request.id("10000" + user.getAge());
request.source(JSONObject.toJSONString(user), XContentType.JSON);
bulkRequest.add(request);
});
BulkResponse response = client.bulk(bulkRequest, RequestOptions.DEFAULT);
System.out.println("批量插入是否失败:" + response.hasFailures());
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());
}
}
client.close();
}
10、批量删除索引中的数据
void batchDeleteDataFromIndex() throws Exception {
RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("localhost", 9200, "http")));
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");
request.id("10000" + user.getAge());
bulkRequest.add(request);
});
BulkResponse response = client.bulk(bulkRequest, RequestOptions.DEFAULT);
System.out.println("批量删除是否失败:" + response.hasFailures());
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());
}
}
client.close();
}
11、高级查询之查询全部数据
void advancedQueryFromAllData() throws Exception {
RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("localhost", 9200, "http")));
SearchRequest request = new SearchRequest();
request.indices("user");
SearchSourceBuilder builder = new SearchSourceBuilder();
builder.query(QueryBuilders.matchAllQuery());
request.source(builder);
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
for (SearchHit hit : response.getHits().getHits()) {
User user = JSONObject.parseObject(hit.getSourceAsString(), User.class);
System.out.println("姓名:" + user.getName() + ";性别:" + user.getSex() + ";年龄:" + user.getAge());
}
client.close();
}
12、高级查询之term精准匹配
void advancedQueryByTerm() throws Exception {
RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("localhost", 9200, "http")));
SearchRequest request = new SearchRequest();
request.indices("user");
SearchSourceBuilder builder = new SearchSourceBuilder();
builder.query(QueryBuilders.termQuery("sex", "男"));
request.source(builder);
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
for (SearchHit hit : response.getHits().getHits()) {
User user = JSONObject.parseObject(hit.getSourceAsString(), User.class);
System.out.println("姓名:" + user.getName() + ";性别:" + user.getSex() + ";年龄:" + user.getAge());
}
client.close();
}
13、高级查询之分页查询
void advancedQueryByPage() throws Exception {
RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("localhost", 9200, "http")));
SearchRequest request = new SearchRequest();
request.indices("user");
SearchSourceBuilder builder = new SearchSourceBuilder();
builder.query(QueryBuilders.matchAllQuery());
int currentPage = 1;
int pageSize = 5;
int from = (currentPage - 1) * pageSize;
builder.from(from);
builder.size(pageSize);
request.source(builder);
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
for (SearchHit hit : response.getHits().getHits()) {
User user = JSONObject.parseObject(hit.getSourceAsString(), User.class);
System.out.println("姓名:" + user.getName() + ";性别:" + user.getSex() + ";年龄:" + user.getAge());
}
client.close();
}
14、高级查询之排序查询
void advancedQueryBySort() throws Exception {
RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("localhost", 9200, "http")));
SearchRequest request = new SearchRequest();
request.indices("user");
SearchSourceBuilder builder = new SearchSourceBuilder();
builder.query(QueryBuilders.matchAllQuery());
builder.sort("age", SortOrder.DESC);
request.source(builder);
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
for (SearchHit hit : response.getHits().getHits()) {
User user = JSONObject.parseObject(hit.getSourceAsString(), User.class);
System.out.println("姓名:" + user.getName() + ";性别:" + user.getSex() + ";年龄:" + user.getAge());
}
client.close();
}
15、高级查询之source获取部分字段内容
void advancedQueryBySource() throws Exception {
RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("localhost", 9200, "http")));
SearchRequest request = new SearchRequest();
request.indices("user");
SearchSourceBuilder builder = new SearchSourceBuilder();
builder.query(QueryBuilders.matchAllQuery());
String[] includes = {"name", "age"};
String[] excludes = {};
builder.fetchSource(includes, excludes);
request.source(builder);
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
for (SearchHit hit : response.getHits().getHits()) {
User user = JSONObject.parseObject(hit.getSourceAsString(), User.class);
System.out.println("姓名:" + user.getName() + ";性别:" + user.getSex() + ";年龄:" + user.getAge());
}
client.close();
}
16、高级查询之should匹配
void advancedQueryByShould() throws Exception {
RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("localhost", 9200, "http")));
SearchRequest request = new SearchRequest();
request.indices("user");
SearchSourceBuilder builder = new SearchSourceBuilder();
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
boolQueryBuilder.should(QueryBuilders.matchQuery("age", 30));
boolQueryBuilder.should(QueryBuilders.matchQuery("sex", "女").boost(10));
builder.query(boolQueryBuilder);
request.source(builder);
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
for (SearchHit hit : response.getHits().getHits()) {
User user = JSONObject.parseObject(hit.getSourceAsString(), User.class);
System.out.println("姓名:" + user.getName() + ";性别:" + user.getSex() + ";年龄:" + user.getAge());
}
client.close();
}
17、高级查询之filter过滤查询
void advancedQueryByFilter() throws Exception {
RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("localhost", 9200, "http")));
SearchRequest request = new SearchRequest();
request.indices("user");
SearchSourceBuilder builder = new SearchSourceBuilder();
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
boolQueryBuilder.filter(QueryBuilders.rangeQuery("age").gte(26).lte(29));
builder.query(boolQueryBuilder);
request.source(builder);
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
for (SearchHit hit : response.getHits().getHits()) {
User user = JSONObject.parseObject(hit.getSourceAsString(), User.class);
System.out.println("姓名:" + user.getName() + ";性别:" + user.getSex() + ";年龄:" + user.getAge());
}
client.close();
}
18、高级查询之模糊查询
void advancedQueryByLike() throws Exception {
RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("localhost", 9200, "http")));
SearchRequest request = new SearchRequest();
request.indices("user");
SearchSourceBuilder builder = new SearchSourceBuilder();
builder.query(QueryBuilders.fuzzyQuery("name.keyword", "张三").fuzziness(Fuzziness.ONE));
request.source(builder);
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
for (SearchHit hit : response.getHits().getHits()) {
User user = JSONObject.parseObject(hit.getSourceAsString(), User.class);
System.out.println("姓名:" + user.getName() + ";性别:" + user.getSex() + ";年龄:" + user.getAge());
}
client.close();
}
19、高级查询之高亮查询
void advancedQueryByHighLight() throws Exception {
RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("localhost", 9200, "http")));
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);
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
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());
}
client.close();
}
20、高级查询之最大值聚合查询
void advancedQueryByMaxValueAggregation() throws Exception {
RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("localhost", 9200, "http")));
SearchRequest request = new SearchRequest();
request.indices("user");
SearchSourceBuilder builder = new SearchSourceBuilder();
AggregationBuilder aggregationBuilder = AggregationBuilders.max("maxAge").field("age");
builder.aggregation(aggregationBuilder);
request.source(builder);
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
Aggregations aggregations = response.getAggregations();
ParsedMax maxAge = aggregations.get("maxAge");
System.out.println("最大年龄:" + maxAge.getValue());
client.close();
}
21、高级查询之分组聚合查询
void advancedQueryByGroupAggregation() throws Exception {
RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("localhost", 9200, "http")));
SearchRequest request = new SearchRequest();
request.indices("user");
SearchSourceBuilder builder = new SearchSourceBuilder();
AggregationBuilder aggregationBuilder = AggregationBuilders.terms("termsSex").field("sex.keyword");
builder.aggregation(aggregationBuilder);
request.source(builder);
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
Aggregations aggregations = response.getAggregations();
ParsedStringTerms termsSex = aggregations.get("termsSex");
for (Terms.Bucket bucket : termsSex.getBuckets()) {
System.out.println("性别:" + bucket.getKeyAsString() + ";数量:" + bucket.getDocCount());
}
client.close();
}
22、根据查询条件计算数据量
void count() throws Exception {
RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("localhost", 9200, "http")));
CountRequest request = new CountRequest();
request.indices("user");
request.query(QueryBuilders.matchAllQuery());
request.indicesOptions(IndicesOptions.fromOptions(true, true, false, false));
CountResponse response = client.count(request, RequestOptions.DEFAULT);
System.out.println("数据总量:" + response.getCount());
client.close();
}
23、根据查询条件滚动查询
void scrollQuery() throws Exception {
RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("localhost", 9200, "http")));
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;
SearchResponse scrollResponce = null;
Scroll scroll = new Scroll(TimeValue.timeValueMinutes(2));
List<String> scrollIds = new ArrayList<>();
for (int i = 0; i < totalPage; i++) {
try {
if (i == 0) {
searchRequest.scroll(scroll);
SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
scrollId = response.getScrollId();
scrollIds.add(scrollId);
}
else {
SearchScrollRequest searchScrollRequest = new SearchScrollRequest(scrollId);
searchScrollRequest.scroll(scroll);
scrollResponce = client.scroll(searchScrollRequest, RequestOptions.DEFAULT);
scrollId = scrollResponce.getScrollId();
scrollIds.add(scrollId);
}
} catch (Exception e) {
e.printStackTrace();
}
}
ClearScrollRequest clearScrollRequest = new ClearScrollRequest();
clearScrollRequest.scrollIds(scrollIds);
try {
client.clearScroll(clearScrollRequest, RequestOptions.DEFAULT);
} catch (IOException e) {
System.out.println("清除滚动查询游标id失败");
e.printStackTrace();
}
System.out.println("滚动查询返回数据:" + scrollResponce);
client.close();
}
24、根据索引名称和文档id查询文档是否存在于ES
void multiQueryById() throws Exception {
RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("localhost", 9200, "http")));
MultiGetRequest request = new MultiGetRequest();
request.add("user", "1000");
request.add("user", "2000");
MultiGetResponse response = client.mget(request, RequestOptions.DEFAULT);
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);
client.close();
}
三、注意
- indice可以设置多个
CountRequest request = new CountRequest("index1", "index2");
CountRequest request = new CountRequest();
request.indices("index1", "index2");
- 索引不存在,查询不报错
request.indicesOptions(IndicesOptions.fromOptions(true, true, false, false));
四、实战
1、批量插入
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 -> {
IndexRequest request = new IndexRequest(ESConstant.PRODUCT_INDEX);
request.id(model.getSkuId().toString());
String jsonString = JSONObject.toJSONString(model);
request.source(jsonString, XContentType.JSON);
bulkRequest.add(request);
});
BulkResponse bulk = client.bulk(bulkRequest, ElasticsearchConfig.COMMON_OPTIONS);
return bulk.hasFailures();
}
}
1.1、对应索引结构
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"
}
}
}
}
}
}
2、聚合查询
public class ESSearchServiceImpl implements ESSearchService {
@Resource
private RestHighLevelClient client;
@Resource
private ProductFeignService productFeignService;
@Override
public SearchResult search(SearchParam param) {
SearchResult result = new SearchResult();
SearchRequest searchRequest = buildSearchRequest(param);
try {
SearchResponse response = client.search(searchRequest, ElasticsearchConfig.COMMON_OPTIONS);
result = buildSearchResult(response, param);
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
private SearchRequest buildSearchRequest(SearchParam param) {
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
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();
String[] s1 = attr.split("_");
String[] s2 = s1[1].split(":");
boolQuery.must(QueryBuilders.termQuery("attrs.attrId", s1[0]));
boolQuery.must(QueryBuilders.termsQuery("attrs.attrValue", s2));
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("_")) {
rangeQuery.lte(s[1]);
} else if (s.length == 1 && param.getSkuPrice().endsWith("_")) {
rangeQuery.gte(s[0]);
}
boolQueryBuilder.filter(rangeQuery);
}
sourceBuilder.query(boolQueryBuilder);
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);
}
int start = (param.getPageNum() - 1) * ESConstant.PAGE_SIZE;
sourceBuilder.from(start).size(ESConstant.PAGE_SIZE);
if (StringUtils.isNotEmpty(param.getKeyword())) {
HighlightBuilder builder = new HighlightBuilder();
builder.preTags("<b style='color:red'>");
builder.postTags("</b>");
builder.field("skuTitle");
sourceBuilder.highlighter(builder);
}
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);
SearchRequest searchRequest = new SearchRequest(new String[]{ESConstant.PRODUCT_INDEX}, sourceBuilder);
return searchRequest;
}
private SearchResult buildSearchResult(SearchResponse response, SearchParam param) {
SearchResult result = new SearchResult();
SearchHits hits = response.getHits();
List<SkuEsModel> products = new ArrayList<>();
SearchHit[] searchHits = hits.getHits();
if (searchHits != null && searchHits.length > 0) {
for (SearchHit hit : searchHits) {
String str = hit.getSourceAsString();
SkuEsModel skuEsModel = JSONObject.parseObject(str, SkuEsModel.class);
if (StringUtils.isNotEmpty(param.getKeyword())) {
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);
Aggregations aggregations = response.getAggregations();
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();
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);
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();
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);
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();
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);
long total = hits.getTotalHits().value;
result.setTotal(total);
int totalPage = (int) total % ESConstant.PAGE_SIZE > 0 ? ((int) total / ESConstant.PAGE_SIZE + 1) : (int) total / ESConstant.PAGE_SIZE;
result.setTotalPage(totalPage);
result.setPageNum(param.getPageNum());
if (param.getAttrs() != null && param.getAttrs().size() > 0) {
List<SearchResult.NavVo> navVos = param.getAttrs().stream().map(attr -> {
SearchResult.NavVo navVo = new SearchResult.NavVo();
String[] s = attr.split("_");
result.getAttrIds().add(Long.parseLong(s[0]));
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());
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]);
}
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>>() {
});
StringBuilder sb = new StringBuilder();
String link = null;
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 {
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;
}
}
private String getLinkByBrandId(String requestUri, String queryString, String key, List<Long> values) {
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;
}
}
}
2.1、对应索引结构
请看 四、实战》1、批量插入》1.1、对应索引结构
|