spring boot项目集成Elasticsearch

举报
小米粒-biubiubiu 发表于 2020/11/30 23:21:05 2020/11/30
【摘要】 一、添加elasticsearch 依赖 <dependency> <groupId>org.elasticsearch</groupId> <artifactId>elasticsearch</artifactId> </dependency> <dependency> <groupId>org.elasticsearch.client</groupId> <arti...

一、添加elasticsearch 依赖


  
  1. <dependency>
  2. <groupId>org.elasticsearchgroupId>
  3. <artifactId>elasticsearchartifactId>
  4. dependency>
  5. <dependency>
  6. <groupId>org.elasticsearch.clientgroupId>
  7. <artifactId>elasticsearch-rest-clientartifactId>
  8. dependency>
  9. <dependency>
  10. <groupId>org.elasticsearch.clientgroupId>
  11. <artifactId>elasticsearch-rest-high-level-clientartifactId>
  12. dependency>

二、在application.yml配置elasticsearch 连接信息


  
  1. elasticsearch:
  2. clusterNodes:
  3. - "10.2.140.31:30869"

三、编写RestHighLevelClient 配置类


  
  1. package com.hikvision.smbg.content.core.config;
  2. import lombok.Data;
  3. import lombok.extern.slf4j.Slf4j;
  4. import org.apache.http.HttpHost;
  5. import org.elasticsearch.client.RestClient;
  6. import org.elasticsearch.client.RestClientBuilder;
  7. import org.elasticsearch.client.RestHighLevelClient;
  8. import org.springframework.beans.factory.DisposableBean;
  9. import org.springframework.beans.factory.FactoryBean;
  10. import org.springframework.boot.context.properties.ConfigurationProperties;
  11. import org.springframework.boot.context.properties.EnableConfigurationProperties;
  12. import org.springframework.context.annotation.Bean;
  13. import org.springframework.context.annotation.Configuration;
  14. import org.springframework.util.CollectionUtils;
  15. import java.util.ArrayList;
  16. import java.util.List;
  17. /**
  18. * @author yiyuxin
  19. * @since 2020-05-13
  20. */
  21. @Slf4j
  22. @Configuration
  23. @EnableConfigurationProperties(ElasticsearchConfig.ElasticsearchProperties.class)
  24. public class ElasticsearchConfig {
  25. private final ElasticsearchProperties elasticsearchProperties;
  26. public ElasticsearchConfig(ElasticsearchProperties elasticsearchProperties) {
  27. this.elasticsearchProperties = elasticsearchProperties;
  28. }
  29. @Bean("highLevelClient")
  30. public RestHighLevelClientFactoryBean highLevelClient() {
  31. return new RestHighLevelClientFactoryBean(elasticsearchProperties);
  32. }
  33. /**
  34. * 实现FactoryBean,自定义获取RestHighLevelClient的bean实例,
  35. * 默认单例(FactoryBean接口的isSingleton方法默认返回true)
  36. * 实现Disposable接口,bean实例销毁的时候关闭RestHighLevelClient连接
  37. */
  38. public static class RestHighLevelClientFactoryBean implements FactoryBean<RestHighLevelClient>, DisposableBean {
  39. private RestHighLevelClient highLevelClient;
  40. private ElasticsearchProperties properties;
  41. public RestHighLevelClientFactoryBean(ElasticsearchProperties elasticsearchProperties) {
  42. this.properties = elasticsearchProperties;
  43. }
  44. @Override
  45. public RestHighLevelClient getObject() {
  46. List clusterNodes = properties.getClusterNodes();
  47. List httpHosts = new ArrayList<>(4);
  48. if (!CollectionUtils.isEmpty(clusterNodes)) {
  49. for (String clusterNode : clusterNodes) {
  50. //以:分隔获取到ip 和 端口
  51. String[] hostPort = clusterNode.split(":");
  52. httpHosts.add(new HttpHost(hostPort[0], Integer.parseInt(hostPort[1])));
  53. }
  54. } else {
  55. //如果没有配置ip和端口,默认为localhost:9200
  56. httpHosts.add(new HttpHost("localhost", 9200));
  57. }
  58. RestClientBuilder clientBuilder = RestClient.builder(httpHosts.toArray(new HttpHost[0])).setRequestConfigCallback(requestConfigBuilder -> {
  59. requestConfigBuilder.setConnectionRequestTimeout(10000); // 从连接池获取连接超时时间
  60. requestConfigBuilder.setConnectTimeout(5000); // 连接服务端超时时间
  61. requestConfigBuilder.setSocketTimeout(5000 * 60); // 读取超时
  62. return requestConfigBuilder;
  63. });
  64. clientBuilder.setHttpClientConfigCallback(httpClientBuilder -> {
  65. httpClientBuilder.setMaxConnTotal(100); //最大连接数
  66. httpClientBuilder.setKeepAliveStrategy((response, context) -> 10 * 60 * 1000); //保活时间
  67. httpClientBuilder.setMaxConnPerRoute(100); //针对一个域名同时间正在使用的最多的连接数
  68. return httpClientBuilder;
  69. });
  70. highLevelClient = new RestHighLevelClient(clientBuilder);
  71. return highLevelClient;
  72. }
  73. @Override
  74. public Class getObjectType() {
  75. return RestHighLevelClient.class;
  76. }
  77. @Override
  78. public void destroy() {
  79. try {
  80. log.info("Closing elasticSearch client");
  81. if (highLevelClient != null) {
  82. highLevelClient.close();
  83. }
  84. } catch (final Exception e) {
  85. log.error("Error closing ElasticSearch client: ", e);
  86. }
  87. }
  88. }
  89. @Data
  90. @ConfigurationProperties(prefix = "elasticsearch")
  91. public static class ElasticsearchProperties {
  92. private List clusterNodes;
  93. }
  94. }

四、使用


  
  1. package com.hikvision.smbg.content.core.rpc.impl;
  2. import com.hikvision.smbg.content.common.dto.document.ContentDocument;
  3. import com.hikvision.smbg.content.common.dto.document.Document;
  4. import com.hikvision.smbg.content.common.exception.ContentCenterException;
  5. import com.hikvision.smbg.content.common.exception.EnumErrorCode;
  6. import com.hikvision.smbg.content.common.util.JsonUtils;
  7. import com.hikvision.smbg.content.core.rpc.EsSyncService;
  8. import lombok.extern.slf4j.Slf4j;
  9. import org.apache.commons.collections4.CollectionUtils;
  10. import org.elasticsearch.action.bulk.BulkItemResponse;
  11. import org.elasticsearch.action.bulk.BulkRequest;
  12. import org.elasticsearch.action.bulk.BulkResponse;
  13. import org.elasticsearch.action.index.IndexRequest;
  14. import org.elasticsearch.action.index.IndexResponse;
  15. import org.elasticsearch.action.support.WriteRequest;
  16. import org.elasticsearch.action.update.UpdateRequest;
  17. import org.elasticsearch.client.RequestOptions;
  18. import org.elasticsearch.client.RestHighLevelClient;
  19. import org.elasticsearch.common.xcontent.XContentType;
  20. import org.elasticsearch.index.query.QueryBuilder;
  21. import org.elasticsearch.index.query.QueryBuilders;
  22. import org.elasticsearch.index.reindex.BulkByScrollResponse;
  23. import org.elasticsearch.index.reindex.UpdateByQueryRequest;
  24. import org.elasticsearch.rest.RestStatus;
  25. import org.elasticsearch.script.Script;
  26. import org.elasticsearch.script.ScriptType;
  27. import org.springframework.beans.factory.annotation.Autowired;
  28. import org.springframework.boot.autoconfigure.elasticsearch.rest.RestClientAutoConfiguration;
  29. import org.springframework.stereotype.Service;
  30. import java.io.IOException;
  31. import java.util.HashMap;
  32. import java.util.List;
  33. import java.util.Map;
  34. import java.util.Objects;
  35. /**
  36. * {@link RestClientAutoConfiguration}
  37. *
  38. * @author yiyuxin
  39. * @since 2020-10-30
  40. */
  41. @Slf4j
  42. @Service
  43. public class EsSyncServiceImpl implements EsSyncService {
  44. /**
  45. * 内容索引
  46. */
  47. private static String index = ContentDocument.class.getAnnotation(Document.class).index();
  48. /**
  49. * 客户端
  50. */
  51. @Autowired
  52. private RestHighLevelClient highLevelClient;
  53. @Override
  54. public void index(ContentDocument document) {
  55. // 构建索引请求
  56. String id = String.valueOf(document.getId());
  57. String source = Objects.requireNonNull(JsonUtils.toJson(document));
  58. IndexRequest request = new IndexRequest(index).id(id).source(source, XContentType.JSON);
  59. // 索引内容文档
  60. IndexResponse response;
  61. try {
  62. response = highLevelClient.index(request, RequestOptions.DEFAULT);
  63. } catch (Exception e) {
  64. log.error("内容索引失败,document={}", source);
  65. throw new ContentCenterException(EnumErrorCode.C_DEFAULT_ERR, e);
  66. }
  67. // 请求结果解析
  68. RestStatus status = response.status();
  69. if (!RestStatus.OK.equals(status) && !RestStatus.CREATED.equals(status)) {
  70. log.error("内容索引失败,document={}, status={}", source, status);
  71. throw new ContentCenterException(EnumErrorCode.C_DEFAULT_ERR);
  72. }
  73. if (log.isDebugEnabled()) {
  74. log.debug("内容索引成功,document={}", source);
  75. }
  76. }
  77. @Override
  78. public void enableOrDisable(List contentIds, Integer contentStatus) {
  79. UpdateByQueryRequest request = new UpdateByQueryRequest(index);
  80. String[] ids = contentIds.stream().map(String::valueOf).toArray(String[]::new);
  81. QueryBuilder query = QueryBuilders.idsQuery().addIds(ids);
  82. request.setQuery(query);
  83. Map<String, Object> params = new HashMap<>(contentIds.size());
  84. for (String id : ids) {
  85. params.put(id, contentStatus);
  86. }
  87. String code = "if(ctx._source.content_status==params[ctx._id]){ctx.op='noop'}"
  88. + "else{ctx._source.content_status=params[ctx._id]}";
  89. Script script = new Script(ScriptType.INLINE, Script.DEFAULT_SCRIPT_LANG, code, params);
  90. request.setScript(script);
  91. request.setRefresh(true);
  92. BulkByScrollResponse response;
  93. try {
  94. response = highLevelClient.updateByQuery(request, RequestOptions.DEFAULT);
  95. } catch (IOException e) {
  96. log.error("内容启用或停用失败,contentIds={},contentStatus={}", contentIds, contentStatus);
  97. throw new ContentCenterException(EnumErrorCode.C_DEFAULT_ERR, e);
  98. }
  99. List failures = response.getBulkFailures();
  100. if (CollectionUtils.isNotEmpty(failures)) {
  101. log.error("内容启用或停用失败,contentIds={},contentStatus={}, failures={}", contentIds, contentStatus, failures);
  102. throw new ContentCenterException(EnumErrorCode.C_DEFAULT_ERR);
  103. }
  104. if (log.isDebugEnabled()) {
  105. log.debug("内容启用或停用成功,contentIds={},contentStatus={}", contentIds, contentStatus);
  106. }
  107. }
  108. @Override
  109. public void syncStatistics(List documents) {
  110. // 构建批量请求
  111. BulkRequest bulkRequest = new BulkRequest(index);
  112. bulkRequest.setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE);
  113. for (ContentDocument document : documents) {
  114. UpdateRequest request = new UpdateRequest();
  115. request.id(String.valueOf(document.getId()));
  116. request.doc(JsonUtils.toJson(document), XContentType.JSON);
  117. bulkRequest.add(request);
  118. }
  119. // 批量请求响应处理
  120. BulkResponse bulkResponse;
  121. try {
  122. bulkResponse = highLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
  123. } catch (IOException e) {
  124. log.error("内容统计数据同步失败,documents={}", JsonUtils.toJson(documents));
  125. throw new ContentCenterException(EnumErrorCode.C_DEFAULT_ERR, e);
  126. }
  127. if (bulkResponse.hasFailures()) {
  128. log.error("内容统计数据同步失败,documents={}, failures={}", JsonUtils.toJson(documents), bulkResponse.buildFailureMessage());
  129. throw new ContentCenterException(EnumErrorCode.C_DEFAULT_ERR);
  130. }
  131. if (log.isDebugEnabled()) {
  132. log.debug("内容统计数据同步成功,documents={}", JsonUtils.toJson(documents));
  133. }
  134. }
  135. }

  
  1. package com.hikvision.smbg.content.core.rpc.impl;
  2. import com.baomidou.mybatisplus.core.metadata.IPage;
  3. import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
  4. import com.hikvision.smbg.content.common.dto.document.ContentDocument;
  5. import com.hikvision.smbg.content.common.dto.document.Document;
  6. import com.hikvision.smbg.content.common.dto.request.ContentSearchRequest;
  7. import com.hikvision.smbg.content.common.dto.request.ContentSearchSuggestRequest;
  8. import com.hikvision.smbg.content.common.dto.response.ContentSearchResponse;
  9. import com.hikvision.smbg.content.common.dto.response.ContentSearchSuggestResponse;
  10. import com.hikvision.smbg.content.common.enums.ContentFromEnum;
  11. import com.hikvision.smbg.content.common.enums.ContentStatusEnum;
  12. import com.hikvision.smbg.content.common.exception.ContentCenterException;
  13. import com.hikvision.smbg.content.common.exception.EnumErrorCode;
  14. import com.hikvision.smbg.content.common.util.AppPermissionBitComputeUtils;
  15. import com.hikvision.smbg.content.common.util.JsonUtils;
  16. import com.hikvision.smbg.content.core.rpc.EsSearchService;
  17. import lombok.extern.slf4j.Slf4j;
  18. import org.apache.commons.lang3.StringUtils;
  19. import org.elasticsearch.action.search.SearchRequest;
  20. import org.elasticsearch.action.search.SearchResponse;
  21. import org.elasticsearch.client.RequestOptions;
  22. import org.elasticsearch.client.RestHighLevelClient;
  23. import org.elasticsearch.index.query.BoolQueryBuilder;
  24. import org.elasticsearch.index.query.QueryBuilders;
  25. import org.elasticsearch.rest.RestStatus;
  26. import org.elasticsearch.search.SearchHit;
  27. import org.elasticsearch.search.SearchHits;
  28. import org.elasticsearch.search.aggregations.AggregationBuilders;
  29. import org.elasticsearch.search.aggregations.Aggregations;
  30. import org.elasticsearch.search.aggregations.BucketOrder;
  31. import org.elasticsearch.search.aggregations.bucket.terms.ParsedStringTerms;
  32. import org.elasticsearch.search.aggregations.bucket.terms.Terms;
  33. import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
  34. import org.elasticsearch.search.builder.SearchSourceBuilder;
  35. import org.elasticsearch.search.sort.SortOrder;
  36. import org.springframework.beans.BeanUtils;
  37. import org.springframework.beans.factory.annotation.Autowired;
  38. import org.springframework.stereotype.Service;
  39. import java.util.ArrayList;
  40. import java.util.List;
  41. import java.util.Objects;
  42. import java.util.Set;
  43. /**
  44. * @author yiyuxin
  45. * @since 2020-10-30
  46. */
  47. @Slf4j
  48. @Service
  49. public class EsSearchServiceImpl implements EsSearchService {
  50. /**
  51. * 内容索引
  52. */
  53. private static String index = ContentDocument.class.getAnnotation(Document.class).index();
  54. /**
  55. * 客户端
  56. */
  57. @Autowired
  58. private RestHighLevelClient highLevelClient;
  59. @Override
  60. public IPage search(ContentSearchRequest request) {
  61. IPage page = new Page<>();
  62. // 1. 查询请求
  63. SearchRequest searchRequest = new SearchRequest(index);
  64. SearchSourceBuilder source = new SearchSourceBuilder();
  65. searchRequest.source(source);
  66. source.trackTotalHits(true);
  67. // 2. 分页
  68. source.from((request.getPage() - 1) * request.getSize());
  69. source.size(request.getSize());
  70. // 3. 排序
  71. if (StringUtils.isNotBlank(request.getSort())
  72. && StringUtils.isNotBlank(request.getOrder())) {
  73. source.sort(request.getSort(), SortOrder.fromString(request.getOrder()));
  74. }
  75. source.sort("gmt_publish", SortOrder.DESC);
  76. source.sort("id", SortOrder.DESC);
  77. // 4. 查询条件
  78. BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
  79. source.query(boolQuery);
  80. // 内容状态
  81. boolQuery.filter().add(QueryBuilders.termQuery("content_status", ContentStatusEnum.ENABLED.getStatus()));
  82. // 内容类型
  83. if (Objects.nonNull(request.getContentType())) {
  84. boolQuery.filter().add(QueryBuilders.termQuery("content_type", request.getContentType()));
  85. }
  86. // 标签 ID
  87. if (Objects.nonNull(request.getLabelId())) {
  88. boolQuery.filter().add(QueryBuilders.termQuery("label_ids", request.getLabelId()));
  89. }
  90. // 一级行业 ID
  91. if (Objects.nonNull(request.getOneIndustryId())) {
  92. boolQuery.filter().add(QueryBuilders.termQuery("one_industry_id", request.getOneIndustryId()));
  93. }
  94. // 二级行业 ID
  95. if (Objects.nonNull(request.getTwoIndustryId())) {
  96. boolQuery.filter().add(QueryBuilders.termQuery("two_industry_id", request.getTwoIndustryId()));
  97. }
  98. // 应用权限
  99. if (Objects.nonNull(request.getApp())) {
  100. Set scopes = AppPermissionBitComputeUtils.getAllPermissionValueSetByAppPermissionBit(request.getApp());
  101. scopes.add(0);
  102. boolQuery.filter().add(QueryBuilders.termsQuery("scope", scopes));
  103. }
  104. // 关键词
  105. if (StringUtils.isNotBlank(request.getKeyword())) {
  106. BoolQueryBuilder keywordBoolQuery = QueryBuilders.boolQuery();
  107. boolQuery.must().add(keywordBoolQuery);
  108. // 内容标题
  109. keywordBoolQuery.should().add(QueryBuilders.wildcardQuery("title", StringUtils.join("*", request.getKeyword(), "*")));
  110. // 内容简介
  111. keywordBoolQuery.should().add(QueryBuilders.termQuery("profile", request.getKeyword()));
  112. }
  113. // 创建人
  114. if (StringUtils.isNotBlank(request.getCreator())) {
  115. BoolQueryBuilder creatorBoolQuery = QueryBuilders.boolQuery();
  116. boolQuery.must().add(creatorBoolQuery);
  117. // 平台
  118. creatorBoolQuery.should().add(QueryBuilders.termQuery("from", ContentFromEnum.PLATFORM.getCode()));
  119. // 商家
  120. BoolQueryBuilder mCreatorBoolQuery = QueryBuilders.boolQuery();
  121. creatorBoolQuery.should().add(mCreatorBoolQuery);
  122. mCreatorBoolQuery.must(QueryBuilders.termQuery("user_id", request.getCreator()));
  123. mCreatorBoolQuery.must(QueryBuilders.termQuery("from", ContentFromEnum.MERCHANT.getCode()));
  124. }
  125. if (log.isDebugEnabled()) {
  126. log.debug("内容搜索,query={}", source);
  127. }
  128. // 5. 内容查询
  129. SearchResponse searchResponse;
  130. try {
  131. searchResponse = highLevelClient.search(searchRequest, RequestOptions.DEFAULT);
  132. } catch (Exception e) {
  133. log.error("内容搜索失败,request={}", JsonUtils.toJson(request));
  134. throw new ContentCenterException(EnumErrorCode.C_DEFAULT_ERR, e);
  135. }
  136. // 6. 搜索结果处理
  137. RestStatus status = searchResponse.status();
  138. if (!status.equals(RestStatus.OK)) {
  139. log.error("内容搜索失败,request={}, status={}", JsonUtils.toJson(request), status);
  140. throw new ContentCenterException(EnumErrorCode.C_DEFAULT_ERR);
  141. }
  142. // 总数量
  143. SearchHits hits = searchResponse.getHits();
  144. long total = hits.getTotalHits().value;
  145. if (total == 0) {
  146. return page;
  147. }
  148. page.setTotal(total);
  149. // 数据记录
  150. List records = new ArrayList<>(request.getSize());
  151. page.setRecords(records);
  152. SearchHit[] hitArr = hits.getHits();
  153. for (SearchHit hit : hitArr) {
  154. ContentDocument document = JsonUtils.fromJson(hit.getSourceAsString(), ContentDocument.class);
  155. if (Objects.isNull(document)) continue;
  156. ContentSearchResponse response = new ContentSearchResponse();
  157. BeanUtils.copyProperties(document, response);
  158. page.getRecords().add(response);
  159. }
  160. return page;
  161. }
  162. @Override
  163. public ContentSearchSuggestResponse suggest(ContentSearchSuggestRequest request) {
  164. // 1. 查询请求
  165. SearchRequest searchRequest = new SearchRequest(index);
  166. SearchSourceBuilder source = new SearchSourceBuilder();
  167. searchRequest.source(source);
  168. source.size(0);
  169. // 2. 查询条件
  170. BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
  171. source.query(boolQuery);
  172. // 内容状态
  173. boolQuery.filter().add(QueryBuilders.termQuery("content_status", ContentStatusEnum.ENABLED.getStatus()));
  174. // 关键字
  175. BoolQueryBuilder keywordBoolQuery = QueryBuilders.boolQuery();
  176. boolQuery.must().add(keywordBoolQuery);
  177. // 内容标题
  178. keywordBoolQuery.should().add(QueryBuilders.wildcardQuery("title", StringUtils.join("*", request.getKeyword(), "*")));
  179. // 内容简介
  180. keywordBoolQuery.should().add(QueryBuilders.termQuery("profile", request.getKeyword()));
  181. // 内容类型
  182. boolQuery.filter().add(QueryBuilders.termQuery("content_type", request.getContentType()));
  183. // 应用权限
  184. if (Objects.nonNull(request.getApp())) {
  185. Set scopes = AppPermissionBitComputeUtils.getAllPermissionValueSetByAppPermissionBit(request.getApp());
  186. scopes.add(0);
  187. boolQuery.filter().add(QueryBuilders.termsQuery("scope", scopes));
  188. }
  189. // 内容发布人
  190. if (StringUtils.isNotBlank(request.getCreator())) {
  191. BoolQueryBuilder creatorBoolQuery = QueryBuilders.boolQuery();
  192. boolQuery.must().add(creatorBoolQuery);
  193. // 平台
  194. creatorBoolQuery.should().add(QueryBuilders.termQuery("from", ContentFromEnum.PLATFORM.getCode()));
  195. // 商家
  196. BoolQueryBuilder mCreatorBoolQuery = QueryBuilders.boolQuery();
  197. creatorBoolQuery.should().add(mCreatorBoolQuery);
  198. mCreatorBoolQuery.must(QueryBuilders.termQuery("user_id", request.getCreator()));
  199. mCreatorBoolQuery.must(QueryBuilders.termQuery("from", ContentFromEnum.MERCHANT.getCode()));
  200. }
  201. // 聚合
  202. TermsAggregationBuilder aggs = AggregationBuilders.terms("title-terms")
  203. .field("title").size(10).order(BucketOrder.compound(BucketOrder.count(false), BucketOrder.key(false)));
  204. source.aggregation(aggs);
  205. if (log.isDebugEnabled()) {
  206. log.debug("内容搜索提示,query={}", source);
  207. }
  208. // 3. 内容查询
  209. SearchResponse searchResponse;
  210. try {
  211. searchResponse = highLevelClient.search(searchRequest, RequestOptions.DEFAULT);
  212. } catch (Exception e) {
  213. log.error("内容搜索提示查询失败,request={}", request);
  214. throw new ContentCenterException(EnumErrorCode.C_DEFAULT_ERR, e);
  215. }
  216. // 4. 搜索结果处理
  217. RestStatus status = searchResponse.status();
  218. if (!status.equals(RestStatus.OK)) {
  219. log.error("内容搜索提示查询失败,request={}, status={}", request, status);
  220. throw new ContentCenterException(EnumErrorCode.C_DEFAULT_ERR);
  221. }
  222. ContentSearchSuggestResponse response = new ContentSearchSuggestResponse(request.getContentType(),
  223. new ArrayList<>(10));
  224. Aggregations aggregations = searchResponse.getAggregations();
  225. ParsedStringTerms terms = aggregations.get("title-terms");
  226. List buckets = terms.getBuckets();
  227. for (Terms.Bucket bucket : buckets) {
  228. response.getSuggests().add(bucket.getKeyAsString());
  229. }
  230. return response;
  231. }
  232. }

 

文章来源: blog.csdn.net,作者:血煞风雨城2018,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/qq_31905135/article/details/109814141

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。