【Elasticsearch系列五】Java API

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。
img

  • 推荐:kwan 的首页,持续学习,不断总结,共同进步,活到老学到老
  • 导航
    • 檀越剑指大厂系列:全面总结 java 核心技术,jvm,并发编程 redis,kafka,Spring,微服务等
    • 常用开发工具系列:常用的开发工具,IDEA,Mac,Alfred,Git,typora 等
    • 数据库系列:详细总结了常用数据库 mysql 技术点,以及工作中遇到的 mysql 问题等
    • 新空间代码工作室:提供各种软件服务,承接各种毕业设计,毕业论文等
    • 懒人运维系列:总结好用的命令,解放双手不香吗?能用一个命令完成绝不用两个操作
    • 数据结构与算法系列:总结数据结构和算法,不同类型针对性训练,提升编程思维,剑指大厂

非常期待和您一起在这个小小的网络世界里共同探索、学习和成长。💝💝💝 ✨✨ 欢迎订阅本专栏 ✨✨

博客目录

      • 1.document
        • 1.pom
        • 2.yaml
        • 3.config
        • 4.get
        • 5.add
        • 6.update
        • 7.delete
        • 8.bulk
      • 2.index
        • 1.创建索引
        • 2.删除索引
        • 3.是否存在索引
        • 4.关闭索引
        • 5.打开索引
      • 3.search
        • 1.all
        • 2.page
        • 3.ids
        • 4.match
        • 5.term
        • 6.multi_match
        • 7.bool
        • 8.filter
        • 9.sort
      • 4.sql 功能
      • 5.学成在线站内搜索模块
        • 1.mysql 导入学生数据
        • 2.创建索引 xc_course
        • 3.创建映射
        • 4.logstash 创建模板文件
        • 5.logstash 配置 mysql.conf
        • 6.启动
        • 7.后端代码
          • 7.1.Controller
          • 7.2.service

代码地址

1.document

1.pom
<dependencies><!--es客户端--><dependency><groupId>org.elasticsearch.client</groupId><!-- low:偏向底层。high :高級封装。足够。--><artifactId>elasticsearch-rest-high-level-client</artifactId><version>7.3.0</version><exclusions><exclusion><groupId>org.elasticsearch</groupId><artifactId>elasticsearch</artifactId></exclusion></exclusions></dependency><dependency><groupId>org.elasticsearch</groupId><artifactId>elasticsearch</artifactId><version>7.3.0</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId><version>2.0.6.RELEASE</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope><version>2.0.6.RELEASE</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.16.10</version></dependency>
</dependencies>
2.yaml
spring:application:name: search-service
kwan:elasticsearch:hostlist: 47.119.162.180:9200 #多个节点用逗号分隔
3.config
@Configuration
public class ElasticsearchConfig {@Value("${kwan.elasticsearch.hostlist}")private String hostlist;@Bean(destroyMethod = "close")public RestHighLevelClient restHighLevelClient() {String[] split = hostlist.split(",");HttpHost[] httpHostsArray = new HttpHost[split.length];for (int i = 0; i < split.length; i++) {String item = split[i];httpHostsArray[i] = new HttpHost(item.split(":")[0], Integer.parseInt(item.split(":")[1]), "http");}return new RestHighLevelClient(RestClient.builder(httpHostsArray));}
}
4.get
@Slf4j
@SpringBootTest(classes = SearchApplication.class)
@RunWith(SpringRunner.class)
public class TestDocument_01_get {@AutowiredRestHighLevelClient client;@Testpublic void testGet() throws IOException {//构建请求GetRequest getRequest = new GetRequest("test_post", "1");//添加可选参数String[] includes = new String[]{"id", "comment"};String[] excludes = Strings.EMPTY_ARRAY;FetchSourceContext fetchSourceContext = new FetchSourceContext(true, includes, excludes);getRequest.fetchSourceContext(fetchSourceContext);//同步查询GetResponse getResponse = client.get(getRequest, RequestOptions.DEFAULT);//获取结果if (getResponse.isExists()) {log.info(getResponse.getId());log.info(String.valueOf(getResponse.getVersion()));log.info(getResponse.getSourceAsString());//以string获取数据log.info(String.valueOf(getResponse.getSourceAsBytes()));以Bytes获取数据log.info(String.valueOf(getResponse.getSourceAsMap()));//以Map获取数据} else {log.info("数据不存在");}}
}
@Testpublic void testGet() {//构建请求GetRequest getRequest = new GetRequest("test_post", "1");//添加可选参数String[] includes = new String[]{"id", "title"};String[] excludes = Strings.EMPTY_ARRAY;FetchSourceContext fetchSourceContext = new FetchSourceContext(true, includes, excludes);getRequest.fetchSourceContext(fetchSourceContext);//设置监听器ActionListener<GetResponse> listener = new ActionListener<GetResponse>() {//成功时public void onResponse(GetResponse getResponse) {log.info(getResponse.getId());log.info(String.valueOf(getResponse.getVersion()));log.info(getResponse.getSourceAsString());}//失败时public void onFailure(Exception e) {e.printStackTrace();log.info("数据获取异常");}};//异步查询client.getAsync(getRequest, RequestOptions.DEFAULT, listener);try {Thread.sleep(5000);} catch (InterruptedException e) {e.printStackTrace();}}
5.add
@Testpublic void testAdd() throws IOException {//构建请求IndexRequest request = new IndexRequest("test_post");request.id("5");//构建文档数据String jsonString = "{\n" +"  \"user\":\"tomas\",\n" +"  \"postDate\":\"2019-07-18\",\n" +"  \"message\":\"trying out es1\"\n" +"}";request.source(jsonString, XContentType.JSON);//同步IndexResponse indexResponse = client.index(request, RequestOptions.DEFAULT);//获取结果log.info(indexResponse.getIndex());log.info(indexResponse.getId());log.info(String.valueOf(indexResponse.getResult()));if (indexResponse.getResult() == DocWriteResponse.Result.CREATED) {DocWriteResponse.Result result = indexResponse.getResult();log.info("CREATE" + result);} else if (indexResponse.getResult() == DocWriteResponse.Result.UPDATED) {DocWriteResponse.Result result = indexResponse.getResult();log.info("UPDATED" + result);} else {log.info("其他操作");}//获取分片信息ReplicationResponse.ShardInfo shardInfo = indexResponse.getShardInfo();if (shardInfo.getTotal() != shardInfo.getSuccessful()) {log.info("处理成功的分片数少于总分片!");}if (shardInfo.getFailed() > 0) {for (ReplicationResponse.ShardInfo.Failure failure : shardInfo.getFailures()) {String reason = failure.reason();//每一个错误的原因log.info(reason);}}}
 @Testpublic void testAdd() throws IOException {//构建请求IndexRequest request = new IndexRequest("test_post");request.id("6");//构建文档数据Map<String, Object> jsonMap = new HashMap<String, Object>();jsonMap.put("user", "tomas");jsonMap.put("postDate", "2019-07-18");jsonMap.put("message", "trying out es1");request.source(jsonMap);//同步执行IndexResponse indexResponse = client.index(request, RequestOptions.DEFAULT);//获取结果log.info(indexResponse.getIndex());log.info(indexResponse.getId());log.info(String.valueOf(indexResponse.getResult()));if (indexResponse.getResult() == DocWriteResponse.Result.CREATED) {DocWriteResponse.Result result = indexResponse.getResult();log.info("CREATE" + result);} else if (indexResponse.getResult() == DocWriteResponse.Result.UPDATED) {DocWriteResponse.Result result = indexResponse.getResult();log.info("UPDATED" + result);}ReplicationResponse.ShardInfo shardInfo = indexResponse.getShardInfo();if (shardInfo.getTotal() != shardInfo.getSuccessful()) {log.info("处理成功的分片数少于总分片!");}if (shardInfo.getFailed() > 0) {for (ReplicationResponse.ShardInfo.Failure failure : shardInfo.getFailures()) {String reason = failure.reason();//每一个错误的原因log.info(reason);}}}
@Testpublic void testAdd() throws IOException {//构建请求IndexRequest request = new IndexRequest("test_post");request.id("7");//构建文档数据XContentBuilder builder = XContentFactory.jsonBuilder();builder.startObject();{builder.field("user", "tomas");builder.field("message", "trying out es1");builder.timeField("postDate", "2019-07-18");}builder.endObject();request.source(builder);//同步执行IndexResponse indexResponse = client.index(request, RequestOptions.DEFAULT);//获取结果log.info(indexResponse.getIndex());log.info(indexResponse.getId());log.info(String.valueOf(indexResponse.getResult()));if (indexResponse.getResult() == DocWriteResponse.Result.CREATED) {DocWriteResponse.Result result = indexResponse.getResult();log.info("CREATE" + result);} else if (indexResponse.getResult() == DocWriteResponse.Result.UPDATED) {DocWriteResponse.Result result = indexResponse.getResult();log.info("UPDATED" + result);}ReplicationResponse.ShardInfo shardInfo = indexResponse.getShardInfo();if (shardInfo.getTotal() != shardInfo.getSuccessful()) {log.info("处理成功的分片数少于总分片!");}if (shardInfo.getFailed() > 0) {for (ReplicationResponse.ShardInfo.Failure failure : shardInfo.getFailures()) {String reason = failure.reason();//每一个错误的原因log.info(reason);}}}
@Testpublic void testAdd() throws IOException {//构建请求IndexRequest request = new IndexRequest("test_post");request.id("9");//构建文档数据request.source("user", "tomas","message", "trying out es1","postDate", "2019-07-18");//同步执行IndexResponse indexResponse = client.index(request, RequestOptions.DEFAULT);//获取结果log.info(indexResponse.getIndex());log.info(indexResponse.getId());log.info(String.valueOf(indexResponse.getResult()));if (indexResponse.getResult() == DocWriteResponse.Result.CREATED) {DocWriteResponse.Result result = indexResponse.getResult();log.info("CREATE" + result);} else if (indexResponse.getResult() == DocWriteResponse.Result.UPDATED) {DocWriteResponse.Result result = indexResponse.getResult();log.info("UPDATED" + result);}ReplicationResponse.ShardInfo shardInfo = indexResponse.getShardInfo();if (shardInfo.getTotal() != shardInfo.getSuccessful()) {log.info("处理成功的分片数少于总分片!");}if (shardInfo.getFailed() > 0) {for (ReplicationResponse.ShardInfo.Failure failure : shardInfo.getFailures()) {String reason = failure.reason();//每一个错误的原因log.info(reason);}}}
@Testpublic void testAdd() throws IOException {//构建请求IndexRequest request = new IndexRequest("test_post");request.id("10");//构建文档数据String jsonString = "{\n" +"  \"user\":\"tomas\",\n" +"  \"postDate\":\"2019-07-18\",\n" +"  \"message\":\"trying out es1\"\n" +"}";request.source(jsonString, XContentType.JSON);//设置超时时间request.timeout("1s");request.timeout(TimeValue.timeValueSeconds(1));//手动维护版本号request.version(4);request.versionType(VersionType.EXTERNAL);//同步执行IndexResponse indexResponse = client.index(request, RequestOptions.DEFAULT);//获取结果log.info(indexResponse.getIndex());log.info(indexResponse.getId());log.info(String.valueOf(indexResponse.getResult()));if (indexResponse.getResult() == DocWriteResponse.Result.CREATED) {DocWriteResponse.Result result = indexResponse.getResult();log.info("CREATE" + result);} else if (indexResponse.getResult() == DocWriteResponse.Result.UPDATED) {DocWriteResponse.Result result = indexResponse.getResult();log.info("UPDATED" + result);}ReplicationResponse.ShardInfo shardInfo = indexResponse.getShardInfo();if (shardInfo.getTotal() != shardInfo.getSuccessful()) {log.info("处理成功的分片数少于总分片!");}if (shardInfo.getFailed() > 0) {for (ReplicationResponse.ShardInfo.Failure failure : shardInfo.getFailures()) {String reason = failure.reason();//每一个错误的原因log.info(reason);}}}
6.update
@Testpublic void testUpdate() throws IOException {//创建请求UpdateRequest request = new UpdateRequest("test_post", "5");Map<String, Object> jsonMap = new HashMap<>();jsonMap.put("user", "tomas Lee");request.doc(jsonMap);request.timeout("1s");request.retryOnConflict(3);//重试次数//同步执行UpdateResponse updateResponse = client.update(request, RequestOptions.DEFAULT);//获取结果updateResponse.getId();updateResponse.getIndex();//判断结果if (updateResponse.getResult() == DocWriteResponse.Result.CREATED) {DocWriteResponse.Result result = updateResponse.getResult();log.info("CREATED:" + result);} else if (updateResponse.getResult() == DocWriteResponse.Result.UPDATED) {DocWriteResponse.Result result = updateResponse.getResult();log.info("UPDATED:" + result);} else if (updateResponse.getResult() == DocWriteResponse.Result.DELETED) {DocWriteResponse.Result result = updateResponse.getResult();log.info("DELETED:" + result);} else if (updateResponse.getResult() == DocWriteResponse.Result.NOOP) {//没有操作DocWriteResponse.Result result = updateResponse.getResult();log.info("NOOP:" + result);}}
7.delete
@Testpublic void testDelete() throws IOException {//创建请求DeleteRequest request = new DeleteRequest("test_post", "3");//执行DeleteResponse deleteResponse = client.delete(request, RequestOptions.DEFAULT);//获取结果deleteResponse.getId();deleteResponse.getIndex();DocWriteResponse.Result result = deleteResponse.getResult();log.info(result.toString());}
8.bulk
@Testpublic void testBulk() throws IOException {//创建请求BulkRequest request = new BulkRequest();request.add(new IndexRequest("post").id("1").source(XContentType.JSON, "field", "1"));request.add(new IndexRequest("post").id("2").source(XContentType.JSON, "field", "2"));request.add(new UpdateRequest("post", "1").doc(XContentType.JSON, "field", "3"));request.add(new DeleteRequest("post").id("2"));//执行BulkResponse bulkResponse = client.bulk(request, RequestOptions.DEFAULT);//获取结果for (BulkItemResponse itemResponse : bulkResponse) {DocWriteResponse response = itemResponse.getResponse();switch (itemResponse.getOpType()) {case INDEX:IndexResponse indexResponse = (IndexResponse) response;log.info("INDEX:" + indexResponse.getResult());break;case CREATE:IndexResponse createResponse = (IndexResponse) response;log.info("CREATE:" + createResponse.getResult());break;case UPDATE:UpdateResponse updateResponse = (UpdateResponse) response;log.info("UPDATE:" + updateResponse.getResult());break;case DELETE:DeleteResponse deleteResponse = (DeleteResponse) response;log.info("DELETE:" + deleteResponse.getResult());break;}}}

2.index

1.创建索引
@SpringBootTest
@RunWith(SpringRunner.class)
public class TestIndex_01_Create {@Autowiredprivate RestHighLevelClient client;//创建索引@Testpublic void testCreateIndex() throws IOException {
//        PUT /my_index
//        {
//            "settings": {
//            "number_of_shards": 1,
//                    "number_of_replicas": 1
//        },
//            "mappings": {
//            "properties": {
//                "field1":{
//                    "type": "text"
//                },
//                "field2":{
//                    "type": "text"
//                }
//            }
//        },
//            "aliases": {
//            "default_index": {}
//        }
//        }//创建索引对象CreateIndexRequest createIndexRequest = new CreateIndexRequest("itheima_book");//设置参数createIndexRequest.settings(Settings.builder().put("number_of_shards", "1").put("number_of_replicas", "0"));//指定映射1createIndexRequest.mapping(" {\n" +" \t\"properties\": {\n" +"            \"name\":{\n" +"             \"type\":\"keyword\"\n" +"           },\n" +"           \"description\": {\n" +"              \"type\": \"text\"\n" +"           },\n" +"            \"price\":{\n" +"             \"type\":\"long\"\n" +"           },\n" +"           \"pic\":{\n" +"             \"type\":\"text\",\n" +"             \"index\":false\n" +"           }\n" +" \t}\n" +"}", XContentType.JSON);//设置别名createIndexRequest.alias(new Alias("itheima_index_new"));// 额外参数//设置超时时间createIndexRequest.setTimeout(TimeValue.timeValueMinutes(2));//设置主节点超时时间createIndexRequest.setMasterTimeout(TimeValue.timeValueMinutes(1));//在创建索引API返回响应之前等待的活动分片副本的数量,以int形式表示createIndexRequest.waitForActiveShards(ActiveShardCount.from(2));createIndexRequest.waitForActiveShards(ActiveShardCount.DEFAULT);//操作索引的客户端IndicesClient indices = client.indices();//执行创建索引库CreateIndexResponse createIndexResponse = indices.create(createIndexRequest, RequestOptions.DEFAULT);//得到响应boolean acknowledged = createIndexResponse.isAcknowledged();//得到响应 指示是否在超时前为索引中的每个分片启动了所需数量的碎片副本boolean shardsAcknowledged = createIndexResponse.isShardsAcknowledged();System.out.println("acknowledged:" + acknowledged);System.out.println("shardsAcknowledged:" + shardsAcknowledged);}
}
@SpringBootTest
@RunWith(SpringRunner.class)
public class TestIndex_04_Async {@Autowiredprivate RestHighLevelClient client;//创建索引异步方式@Testpublic void testCreateIndexAsync() {//创建索引对象CreateIndexRequest createIndexRequest = new CreateIndexRequest("itheima_book");//设置参数createIndexRequest.settings(Settings.builder().put("number_of_shards", "1").put("number_of_replicas", "0"));//指定映射1createIndexRequest.mapping(" {\n" +" \t\"properties\": {\n" +"            \"name\":{\n" +"             \"type\":\"keyword\"\n" +"           },\n" +"           \"description\": {\n" +"              \"type\": \"text\"\n" +"           },\n" +"            \"price\":{\n" +"             \"type\":\"long\"\n" +"           },\n" +"           \"pic\":{\n" +"             \"type\":\"text\",\n" +"             \"index\":false\n" +"           }\n" +" \t}\n" +"}", XContentType.JSON);//设置别名createIndexRequest.alias(new Alias("itheima_index_new"));// 额外参数//设置超时时间createIndexRequest.setTimeout(TimeValue.timeValueMinutes(2));//设置主节点超时时间createIndexRequest.setMasterTimeout(TimeValue.timeValueMinutes(1));//在创建索引API返回响应之前等待的活动分片副本的数量,以int形式表示createIndexRequest.waitForActiveShards(ActiveShardCount.from(2));createIndexRequest.waitForActiveShards(ActiveShardCount.DEFAULT);//操作索引的客户端IndicesClient indices = client.indices();//执行创建索引库ActionListener<CreateIndexResponse> listener = new ActionListener<CreateIndexResponse>() {@Overridepublic void onResponse(CreateIndexResponse createIndexResponse) {//得到响应(全部)boolean acknowledged = createIndexResponse.isAcknowledged();//得到响应 指示是否在超时前为索引中的每个分片启动了所需数量的碎片副本boolean shardsAcknowledged = createIndexResponse.isShardsAcknowledged();System.out.println("acknowledged:" + acknowledged);System.out.println("shardsAcknowledged:" + shardsAcknowledged);}@Overridepublic void onFailure(Exception e) {e.printStackTrace();}};client.indices().createAsync(createIndexRequest, RequestOptions.DEFAULT, listener);try {Thread.sleep(5000);} catch (InterruptedException e) {e.printStackTrace();}}
}
2.删除索引
@Testpublic void testDeleteIndex() throws IOException {//创建删除索引请求DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest("itheima_book");//        执行AcknowledgedResponse delete = client.indices().delete(deleteIndexRequest, RequestOptions.DEFAULT);//得到相应boolean acknowledged = delete.isAcknowledged();System.out.println("acknowledged:" + acknowledged);}
3.是否存在索引
 @Testpublic void testExistIndex() throws IOException {GetIndexRequest request = new GetIndexRequest("itheima_book");//参数request.local(false);//从主节点返回本地索引信息状态request.humanReadable(true);//以适合人类的格式返回request.includeDefaults(false);//是否返回每个索引的所有默认配置boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);System.out.println("exists:" + exists);}
4.关闭索引
@Testpublic void testCloseIndex() throws IOException {CloseIndexRequest request = new CloseIndexRequest("itheima_book");AcknowledgedResponse close = client.indices().close(request, RequestOptions.DEFAULT);boolean acknowledged = close.isAcknowledged();System.out.println("acknowledged:" + acknowledged);}
5.打开索引
@Testpublic void testOpenIndex() throws IOException {OpenIndexRequest request = new OpenIndexRequest("itheima_book");OpenIndexResponse open = client.indices().open(request, RequestOptions.DEFAULT);boolean acknowledged = open.isAcknowledged();System.out.println("acknowledged:" + acknowledged);}

3.search

1.all
@SpringBootTest
@RunWith(SpringRunner.class)
public class TestSearch_01_all {@AutowiredRestHighLevelClient client;@Testpublic void testSearchAll() throws IOException {
//        GET book/_search
//        {
//            "query": {
//                "match_all": {}
//             }
//        }//1构建搜索请求SearchRequest searchRequest = new SearchRequest("book");SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();searchSourceBuilder.query(QueryBuilders.matchAllQuery());//获取某些字段searchSourceBuilder.fetchSource(new String[]{"name"}, new String[]{});searchRequest.source(searchSourceBuilder);//2执行搜索SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);//3获取结果SearchHits hits = searchResponse.getHits();//数据数据SearchHit[] searchHits = hits.getHits();System.out.println("--------------------------");for (SearchHit hit : searchHits) {String id = hit.getId();float score = hit.getScore();Map<String, Object> sourceAsMap = hit.getSourceAsMap();String name = (String) sourceAsMap.get("name");String description = (String) sourceAsMap.get("description");Double price = (Double) sourceAsMap.get("price");System.out.println("id:" + id);System.out.println("score:" + score);System.out.println("name:" + name);System.out.println("description:" + description);System.out.println("price:" + price);System.out.println("==========================");}}
}
2.page
@Testpublic void testSearchPage() throws IOException {
//    GET book/_search
//    {
//        "query": {
//          "match_all": {}
//       },
//        "from": 0,
//        "size": 2
//    }//1构建搜索请求SearchRequest searchRequest = new SearchRequest("book");SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();searchSourceBuilder.query(QueryBuilders.matchAllQuery());//第几页int page = 1;//每页几个int size = 2;//下标计算int from = (page - 1) * size;searchSourceBuilder.from(from);searchSourceBuilder.size(size);searchRequest.source(searchSourceBuilder);//2执行搜索SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);//3获取结果SearchHits hits = searchResponse.getHits();//数据数据SearchHit[] searchHits = hits.getHits();System.out.println("--------------------------");for (SearchHit hit : searchHits) {String id = hit.getId();float score = hit.getScore();Map<String, Object> sourceAsMap = hit.getSourceAsMap();String name = (String) sourceAsMap.get("name");String description = (String) sourceAsMap.get("description");Double price = (Double) sourceAsMap.get("price");System.out.println("id:" + id);System.out.println("name:" + name);System.out.println("description:" + description);System.out.println("price:" + price);System.out.println("==========================");}}
3.ids
@Testpublic void testSearchIds() throws IOException {
//    GET /book/_search
//    {
//        "query": {
//           "ids" : {
//             "values" : ["1", "4", "100"]
//          }
//     }
//    }//1构建搜索请求SearchRequest searchRequest = new SearchRequest("book");SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();searchSourceBuilder.query(QueryBuilders.idsQuery().addIds("1", "4", "100"));searchRequest.source(searchSourceBuilder);//2执行搜索SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);//3获取结果SearchHits hits = searchResponse.getHits();//数据数据SearchHit[] searchHits = hits.getHits();System.out.println("--------------------------");for (SearchHit hit : searchHits) {String id = hit.getId();float score = hit.getScore();Map<String, Object> sourceAsMap = hit.getSourceAsMap();String name = (String) sourceAsMap.get("name");String description = (String) sourceAsMap.get("description");Double price = (Double) sourceAsMap.get("price");System.out.println("id:" + id);System.out.println("name:" + name);System.out.println("description:" + description);System.out.println("price:" + price);System.out.println("==========================");}}
4.match
@Testpublic void testSearchMatch() throws IOException {
//    GET /book/_search
//    {
//        "query": {
//           "match": {
//            "description": "java程序员"
//        }
//      }
//    }//1构建搜索请求SearchRequest searchRequest = new SearchRequest("book");SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();searchSourceBuilder.query(QueryBuilders.matchQuery("description", "java程序员"));searchRequest.source(searchSourceBuilder);//2执行搜索SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);//3获取结果SearchHits hits = searchResponse.getHits();//数据数据SearchHit[] searchHits = hits.getHits();System.out.println("--------------------------");for (SearchHit hit : searchHits) {String id = hit.getId();float score = hit.getScore();Map<String, Object> sourceAsMap = hit.getSourceAsMap();String name = (String) sourceAsMap.get("name");String description = (String) sourceAsMap.get("description");Double price = (Double) sourceAsMap.get("price");System.out.println("id:" + id);System.out.println("name:" + name);System.out.println("description:" + description);System.out.println("price:" + price);System.out.println("==========================");}}
5.term
@Testpublic void testSearchTerm() throws IOException {
//
//    GET /book/_search
//    {
//        "query": {
//           "term": {
//            "description": "java程序员"
//        }
//      }
//    }//1构建搜索请求SearchRequest searchRequest = new SearchRequest("book");SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();searchSourceBuilder.query(QueryBuilders.termQuery("description", "java程序员"));searchRequest.source(searchSourceBuilder);//2执行搜索SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);//3获取结果SearchHits hits = searchResponse.getHits();//数据数据SearchHit[] searchHits = hits.getHits();System.out.println("--------------------------");for (SearchHit hit : searchHits) {String id = hit.getId();float score = hit.getScore();Map<String, Object> sourceAsMap = hit.getSourceAsMap();String name = (String) sourceAsMap.get("name");String description = (String) sourceAsMap.get("description");Double price = (Double) sourceAsMap.get("price");System.out.println("id:" + id);System.out.println("name:" + name);System.out.println("description:" + description);System.out.println("price:" + price);System.out.println("==========================");}}
6.multi_match
@Testpublic void testSearchMultiMatch() throws IOException {
//    GET /book/_search
//    {
//        "query": {
//          "multi_match": {
//            "query": "java程序员",
//            "fields": ["name", "description"]
//        }
//      }
//    }//1构建搜索请求SearchRequest searchRequest = new SearchRequest("book");SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();searchSourceBuilder.query(QueryBuilders.multiMatchQuery("java程序员", "name", "description"));searchRequest.source(searchSourceBuilder);//2执行搜索SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);//3获取结果SearchHits hits = searchResponse.getHits();//数据数据SearchHit[] searchHits = hits.getHits();System.out.println("--------------------------");for (SearchHit hit : searchHits) {String id = hit.getId();float score = hit.getScore();Map<String, Object> sourceAsMap = hit.getSourceAsMap();String name = (String) sourceAsMap.get("name");String description = (String) sourceAsMap.get("description");Double price = (Double) sourceAsMap.get("price");System.out.println("id:" + id);System.out.println("name:" + name);System.out.println("description:" + description);System.out.println("price:" + price);System.out.println("==========================");}}
7.bool
 @Testpublic void testSearchBool() throws IOException {
//    GET /book/_search
//    {
//        "query": {
//          "bool": {
//            "must": [
//            {
//                "multi_match": {
//                  "query": "java程序员",
//                  "fields": ["name","description"]
//            }
//            }
//      ],
//            "should": [
//            {
//                "match": {
//                "studymodel": "201001"
//            }
//            }
//      ]
//        }
//    }
//    }//1构建搜索请求SearchRequest searchRequest = new SearchRequest("book");SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();//构建multiMatch请求MultiMatchQueryBuilder multiMatchQueryBuilder = QueryBuilders.multiMatchQuery("java程序员", "name", "description");//构建match请求MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("studymodel", "201001");BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();boolQueryBuilder.must(multiMatchQueryBuilder);boolQueryBuilder.should(matchQueryBuilder);searchSourceBuilder.query(boolQueryBuilder);searchRequest.source(searchSourceBuilder);//2执行搜索SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);//3获取结果SearchHits hits = searchResponse.getHits();//数据数据SearchHit[] searchHits = hits.getHits();System.out.println("--------------------------");for (SearchHit hit : searchHits) {String id = hit.getId();float score = hit.getScore();Map<String, Object> sourceAsMap = hit.getSourceAsMap();String name = (String) sourceAsMap.get("name");String description = (String) sourceAsMap.get("description");Double price = (Double) sourceAsMap.get("price");System.out.println("id:" + id);System.out.println("name:" + name);System.out.println("description:" + description);System.out.println("price:" + price);System.out.println("==========================");}}
8.filter
@Testpublic void testSearchFilter() throws IOException {
//    GET /book/_search
//    {
//        "query": {
//          "bool": {
//            "must": [
//            {
//                "multi_match": {
//                "query": "java程序员",
//                        "fields": ["name","description"]
//            }
//            }
//      ],
//            "should": [
//            {
//                "match": {
//                "studymodel": "201001"
//            }
//            }
//          ],
//            "filter": {
//                "range": {
//                    "price": {
//                        "gte": 50,
//                         "lte": 90
//                    }
//                }
//
//            }
//        }
//    }
//    }//1构建搜索请求SearchRequest searchRequest = new SearchRequest("book");SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();//构建multiMatch请求MultiMatchQueryBuilder multiMatchQueryBuilder = QueryBuilders.multiMatchQuery("java程序员", "name", "description");//构建match请求MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("studymodel", "201001");BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();boolQueryBuilder.must(multiMatchQueryBuilder);boolQueryBuilder.should(matchQueryBuilder);boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").gte(50).lte(90));searchSourceBuilder.query(boolQueryBuilder);searchRequest.source(searchSourceBuilder);//2执行搜索SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);//3获取结果SearchHits hits = searchResponse.getHits();//数据数据SearchHit[] searchHits = hits.getHits();System.out.println("--------------------------");for (SearchHit hit : searchHits) {String id = hit.getId();float score = hit.getScore();Map<String, Object> sourceAsMap = hit.getSourceAsMap();String name = (String) sourceAsMap.get("name");String description = (String) sourceAsMap.get("description");Double price = (Double) sourceAsMap.get("price");System.out.println("id:" + id);System.out.println("name:" + name);System.out.println("description:" + description);System.out.println("price:" + price);System.out.println("==========================");}}
9.sort
@Testpublic void testSearchSort() throws IOException {
//    GET /book/_search
//    {
//        "query": {
//        "bool": {
//            "must": [
//            {
//                "multi_match": {
//                "query": "java程序员",
//                        "fields": ["name","description"]
//            }
//            }
//      ],
//            "should": [
//            {
//                "match": {
//                "studymodel": "201001"
//            }
//            }
//      ],
//            "filter": {
//                "range": {
//                    "price": {
//                        "gte": 50,
//                                "lte": 90
//                    }
//                }
//
//            }
//        }
//    },
//        "sort": [
//        {
//            "price": {
//            "order": "asc"
//        }
//        }
//  ]
//    }//1构建搜索请求SearchRequest searchRequest = new SearchRequest("book");SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();//构建multiMatch请求MultiMatchQueryBuilder multiMatchQueryBuilder = QueryBuilders.multiMatchQuery("java程序员", "name", "description");//构建match请求MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("studymodel", "201001");BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();boolQueryBuilder.must(multiMatchQueryBuilder);boolQueryBuilder.should(matchQueryBuilder);boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").gte(50).lte(90));searchSourceBuilder.query(boolQueryBuilder);//按照价格升序searchSourceBuilder.sort("price", SortOrder.ASC);searchRequest.source(searchSourceBuilder);//2执行搜索SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);//3获取结果SearchHits hits = searchResponse.getHits();//数据数据SearchHit[] searchHits = hits.getHits();System.out.println("--------------------------");for (SearchHit hit : searchHits) {String id = hit.getId();float score = hit.getScore();Map<String, Object> sourceAsMap = hit.getSourceAsMap();String name = (String) sourceAsMap.get("name");String description = (String) sourceAsMap.get("description");Double price = (Double) sourceAsMap.get("price");System.out.println("id:" + id);System.out.println("name:" + name);System.out.println("description:" + description);System.out.println("price:" + price);System.out.println("==========================");}}

4.sql 功能

前提 es 拥有白金版功能:

kibana 中管理-》许可管理 开启白金版试用

导入依赖:

<dependency><groupId>org.elasticsearch.plugin</groupId><artifactId>x-pack-sql-jdbc</artifactId><version>7.3.0</version>
</dependency><repositories><repository><id>elastic.co</id><url>https://artifacts.elastic.co/maven</url></repository>
</repositories>

代码:

public class TestJdbc {public static void main(String[] args) {//1创建连接try {Connection connection = DriverManager.getConnection("jdbc:es://http://localhost:9200");//2创建statementStatement statement = connection.createStatement();//3执行sql语句ResultSet resultSet = statement.executeQuery("SELECT * FROM tvs");//4获取结果while (resultSet.next()) {System.out.println(resultSet.getString(1));System.out.println(resultSet.getString(2));System.out.println(resultSet.getString(3));System.out.println(resultSet.getString(4));System.out.println("======================================");}} catch (SQLException e) {e.printStackTrace();}}
}

5.学成在线站内搜索模块

1.mysql 导入学生数据
/*Navicat Premium Data TransferSource Server         : localSource Server Type    : MySQLSource Server Version : 50721Source Host           : localhost:3306Source Schema         : xc_courseTarget Server Type    : MySQLTarget Server Version : 50721File Encoding         : 65001Date: 10/11/2019 02:50:34*/
SETNAMES utf8mb4;SETFOREIGN_KEY_CHECKS = 0;-- ----------------------------
-- Table structure for course_pub
-- ----------------------------
DROP TABLE IF EXISTS `course_pub`;CREATE TABLE `course_pub` (`id` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '主键',`name` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '课程名称',`users` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '适用人群',`mt` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '大分类',`st` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '小分类',`grade` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '课程等级',`studymodel` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '学习模式',`teachmode` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '教育模式',`description` text CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '课程介绍',`timestamp` timestamp(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0) COMMENT '时间戳logstash使用',`charge` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '收费规则,对应数据字典',`valid` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '有效性,对应数据字典',`qq` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '咨询qq',`price` float(10, 2) NULL DEFAULT NULL COMMENT '价格',`price_old` float(10, 2) NULL DEFAULT NULL COMMENT '原价格',`expires` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '过期时间',`start_time` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '课程有效期-开始时间',`end_time` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '课程有效期-结束时间',`pic` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '课程图片',`teachplan` text CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '课程计划',`pub_time` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '发布时间',PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;-- ----------------------------
-- Records of course_pub
-- ----------------------------
INSERT INTO`course_pub`
VALUES('297e7c7c62b888f00162b8a7dec20000','test_java基础33','b1','1-3','1-3-3','200002','201002',NULL,'java 从入门到删库跑路','2019-10-28 11:26:25','203002','204002','32432',NULL,NULL,NULL,NULL,NULL,'group1/M00/00/00/wKgZhV2tIgiAaYVMAAA2T52Dthw246.jpg','{\"children\":[{\"children\":[],\"id\":\"40288f9b6e0c10d8016e0c37f72a0000\",\"pname\":\"1\"},{\"children\":[{\"id\":\"40288581632b593e01632bd53ff10001\",\"mediaFileoriginalname\":\"solr.avi\",\"mediaId\":\"5fbb79a2016c0eb609ecd0cd3dc48016\",\"pname\":\"Hello World\"},{\"id\":\"40288f9b6e106273016e106485f30000\",\"mediaFileoriginalname\":\"lucene.avi\",\"mediaId\":\"c5c75d70f382e6016d2f506d134eee11\",\"pname\":\"java基础\"}],\"id\":\"40288581632b593e01632bd4ec360000\",\"pname\":\"程序入门\"},{\"children\":[{\"id\":\"40288f9b6dce18e3016dcef16d860001\",\"mediaFileoriginalname\":\"solr.avi\",\"mediaId\":\"5fbb79a2016c0eb609ecd0cd3dc48016\",\"pname\":\"三级节点\"}],\"id\":\"40288f9b6dce18e3016dcef12a1d0000\",\"pname\":\"二级节点\"},{\"children\":[{\"id\":\"40288c9a6ca3968e016ca417fa8d0001\",\"mediaFileoriginalname\":\"lucene.avi\",\"mediaId\":\"c5c75d70f382e6016d2f506d134eee11\",\"pname\":\"test04-01\"}],\"id\":\"40288c9a6ca3968e016ca417b4a50000\",\"pname\":\"test04\"},{\"children\":[{\"id\":\"40288581632b593e01632bd5d31f0003\",\"mediaFileoriginalname\":\"solr.avi\",\"mediaId\":\"5fbb79a2016c0eb609ecd0cd3dc48016\",\"pname\":\"表达式\"},{\"id\":\"40288581632b593e01632bd606480004\",\"pname\":\"逻辑运算\"}],\"id\":\"40288581632b593e01632bd597810002\",\"pname\":\"编程基础\"},{\"children\":[{\"id\":\"402881e764034e4301640351f3d70003\",\"pname\":\"一切皆为对象\"}],\"id\":\"402881e764034e430164035091a00002\",\"pname\":\"面向对象\"},{\"children\":[{\"id\":\"402899816ad8457c016ad9282a330001\",\"pname\":\"test06\"}],\"id\":\"402899816ad8457c016ad927ba540000\",\"pname\":\"test05\"}],\"id\":\"4028858162bec7f30162becad8590000\",\"pname\":\"test_java基础33\"}','2019-10-28 11:26:24');INSERT INTO`course_pub`
VALUES('297e7c7c62b888f00162b8a965510001','test_java基础node','test_java基础','1-3','1-3-2','200001','201001',NULL,'test_java基础2test_java基础2test_java基础2test_java基础2test_java基础2test_java基础2test_java基础2test_java基础2test_java基础2test_java基础2','2019-10-24 16:26:34','203001','204001','443242',NULL,NULL,NULL,NULL,NULL,NULL,'{\"children\":[{\"children\":[{\"id\":\"402881e66417407b01641744fc650001\",\"pname\":\"入门程序\"}],\"id\":\"402881e66417407b01641744afc30000\",\"pname\":\"基础知识\"},{\"children\":[],\"id\":\"4028858162e5d6e00162e5e0727d0001\",\"pname\":\"java基础语法\"},{\"children\":[{\"id\":\"4028d0866b158241016b502433d60002\",\"pname\":\"第二节\"}],\"id\":\"4028d0866b158241016b5023f51e0001\",\"pname\":\"第二章\"}],\"id\":\"4028858162e5d6e00162e5e0227b0000\",\"pname\":\"test_java基础2\"}','2019-10-24 16:26:33');SETFOREIGN_KEY_CHECKS = 1;
2.创建索引 xc_course
3.创建映射
PUT /xc_course
{"settings": {"number_of_shards": 1,"number_of_replicas": 0},"mappings": {"properties": {"description" : {"analyzer" : "ik_max_word","search_analyzer": "ik_smart","type" : "text"},"grade" : {"type" : "keyword"},"id" : {"type" : "keyword"},"mt" : {"type" : "keyword"},"name" : {"analyzer" : "ik_max_word","search_analyzer": "ik_smart","type" : "text"},"users" : {"index" : false,"type" : "text"},"charge" : {"type" : "keyword"},"valid" : {"type" : "keyword"},"pic" : {"index" : false,"type" : "keyword"},"qq" : {"index" : false,"type" : "keyword"},"price" : {"type" : "float"},"price_old" : {"type" : "float"},"st" : {"type" : "keyword"},"status" : {"type" : "keyword"},"studymodel" : {"type" : "keyword"},"teachmode" : {"type" : "keyword"},"teachplan" : {"analyzer" : "ik_max_word","search_analyzer": "ik_smart","type" : "text"},"expires" : {"type" : "date","format": "yyyy-MM-dd HH:mm:ss"},"pub_time" : {"type" : "date","format": "yyyy-MM-dd HH:mm:ss"},"start_time" : {"type" : "date","format": "yyyy-MM-dd HH:mm:ss"},"end_time" : {"type" : "date","format": "yyyy-MM-dd HH:mm:ss"}}}
}
4.logstash 创建模板文件

Logstash 的工作是从 MySQL 中读取数据,向 ES 中创建索引,这里需要提前创建 mapping 的模板文件以便 logstash 使用。

在 logstach 的 config 目录创建 xc_course_template.json,内容如下:

{"mappings": {"doc": {"properties": {"charge": {"type": "keyword"},"description": {"analyzer": "ik_max_word","search_analyzer": "ik_smart","type": "text"},"end_time": {"format": "yyyy-MM-dd HH:mm:ss","type": "date"},"expires": {"format": "yyyy-MM-dd HH:mm:ss","type": "date"},"grade": {"type": "keyword"},"id": {"type": "keyword"},"mt": {"type": "keyword"},"name": {"analyzer": "ik_max_word","search_analyzer": "ik_smart","type": "text"},"pic": {"index": false,"type": "keyword"},"price": {"type": "float"},"price_old": {"type": "float"},"pub_time": {"format": "yyyy-MM-dd HH:mm:ss","type": "date"},"qq": {"index": false,"type": "keyword"},"st": {"type": "keyword"},"start_time": {"format": "yyyy-MM-dd HH:mm:ss","type": "date"},"status": {"type": "keyword"},"studymodel": {"type": "keyword"},"teachmode": {"type": "keyword"},"teachplan": {"analyzer": "ik_max_word","search_analyzer": "ik_smart","type": "text"},"users": {"index": false,"type": "text"},"valid": {"type": "keyword"}}}},"template": "xc_course"
}
5.logstash 配置 mysql.conf

ES 采用 UTC 时区问题

ES 采用 UTC 时区,比北京时间早 8 小时,所以 ES 读取数据时让最后更新时间加 8 小时

where timestamp > date_add(:sql_last_value,INTERVAL 8 HOUR)

logstash 每个执行完成会在/config/logstash_metadata 记录执行时间下次以此时间为基准进行增量同步数据到索引库。

6.启动
.\logstash.bat -f ..\config\mysql.conf
7.后端代码

代码地址

7.1.Controller
@RestController
@RequestMapping("/search/course")
public class EsCourseController {@Autowiredprivate EsCourseServiceImpl esCourseServiceImpl;@GetMapping(value = "/list/{page}/{size}")public QueryResponseResult<CoursePub> list(@PathVariable("page") int page, @PathVariable("size") int size, CourseSearchParam courseSearchParam) {return esCourseServiceImpl.list(page, size, courseSearchParam);}
}
7.2.service
@Service
public class EsCourseServiceImpl implements EsCourseService {@Value("${kwan.course.source_field}")private String source_field;@Autowiredprivate RestHighLevelClient restHighLevelClient;/*** 课程搜索** @param page* @param size* @param courseSearchParam* @return*/@Overridepublic QueryResponseResult<CoursePub> list(int page, int size, CourseSearchParam courseSearchParam) {if (courseSearchParam == null) {courseSearchParam = new CourseSearchParam();}//1创建搜索请求对象SearchRequest searchRequest = new SearchRequest("xc_course");SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();//过虑源字段String[] source_field_array = source_field.split(",");searchSourceBuilder.fetchSource(source_field_array, new String[]{});//创建布尔查询对象BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();//搜索条件//根据关键字搜索if (StringUtils.isNotEmpty(courseSearchParam.getKeyword())) {MultiMatchQueryBuilder multiMatchQueryBuilder =QueryBuilders.multiMatchQuery(courseSearchParam.getKeyword(), "name", "description", "teachplan").minimumShouldMatch("70%").field("name", 10);boolQueryBuilder.must(multiMatchQueryBuilder);}if (StringUtils.isNotEmpty(courseSearchParam.getMt())) {//根据一级分类boolQueryBuilder.filter(QueryBuilders.termQuery("mt", courseSearchParam.getMt()));}if (StringUtils.isNotEmpty(courseSearchParam.getSt())) {//根据二级分类boolQueryBuilder.filter(QueryBuilders.termQuery("st", courseSearchParam.getSt()));}if (StringUtils.isNotEmpty(courseSearchParam.getGrade())) {//根据难度等级boolQueryBuilder.filter(QueryBuilders.termQuery("grade", courseSearchParam.getGrade()));}//设置boolQueryBuilder到searchSourceBuildersearchSourceBuilder.query(boolQueryBuilder);//设置分页参数if (page <= 0) {page = 1;}if (size <= 0) {size = 12;}//起始记录下标int from = (page - 1) * size;searchSourceBuilder.from(from);searchSourceBuilder.size(size);//设置高亮HighlightBuilder highlightBuilder = new HighlightBuilder();highlightBuilder.preTags("<font class='eslight'>");highlightBuilder.postTags("</font>");//设置高亮字段highlightBuilder.fields().add(new HighlightBuilder.Field("name"));searchSourceBuilder.highlighter(highlightBuilder);searchRequest.source(searchSourceBuilder);QueryResult<CoursePub> queryResult = new QueryResult();List<CoursePub> list = new ArrayList<>();try {//2执行搜索SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);//3获取响应结果SearchHits hits = searchResponse.getHits();long totalHits = hits.getTotalHits().value;//匹配的总记录数queryResult.setTotal(totalHits);SearchHit[] searchHits = hits.getHits();for (SearchHit hit : searchHits) {CoursePub coursePub = new CoursePub();//源文档Map<String, Object> sourceAsMap = hit.getSourceAsMap();//取出idString id = (String) sourceAsMap.get("id");coursePub.setId(id);//取出nameString name = (String) sourceAsMap.get("name");//取出高亮字段nameMap<String, HighlightField> highlightFields = hit.getHighlightFields();if (highlightFields != null) {HighlightField highlightFieldName = highlightFields.get("name");if (highlightFieldName != null) {Text[] fragments = highlightFieldName.fragments();StringBuffer stringBuffer = new StringBuffer();for (Text text : fragments) {stringBuffer.append(text);}name = stringBuffer.toString();}}coursePub.setName(name);//图片String pic = (String) sourceAsMap.get("pic");coursePub.setPic(pic);//价格Double price = null;try {if (sourceAsMap.get("price") != null) {price = (Double) sourceAsMap.get("price");}} catch (Exception e) {e.printStackTrace();}coursePub.setPrice(price);//旧价格Double price_old = null;try {if (sourceAsMap.get("price_old") != null) {price_old = (Double) sourceAsMap.get("price_old");}} catch (Exception e) {e.printStackTrace();}coursePub.setPrice_old(price_old);//将coursePub对象放入listlist.add(coursePub);}} catch (IOException e) {e.printStackTrace();}queryResult.setList(list);QueryResponseResult<CoursePub> queryResponseResult = new QueryResponseResult<>(CommonCode.SUCCESS, queryResult);return queryResponseResult;}
}

觉得有用的话点个赞 👍🏻 呗。
❤️❤️❤️本人水平有限,如有纰漏,欢迎各位大佬评论批评指正!😄😄😄

💘💘💘如果觉得这篇文对你有帮助的话,也请给个点赞、收藏下吧,非常感谢!👍 👍 👍

🔥🔥🔥Stay Hungry Stay Foolish 道阻且长,行则将至,让我们一起加油吧!🌙🌙🌙

img

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/52853.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

opencv之图像梯度

图像梯度 图像梯度计算的是图像变化的速度。对于图像的边缘部分&#xff0c;其灰度值变化较大&#xff0c;梯度值也较大&#xff1b;相反&#xff0c;对于图像中比较平滑的部分&#xff0c;其灰度值变化较小&#xff0c;相应的梯度值也较小。一般情况下&#xff0c;图像梯度计…

C++11的部分新特性

目录 1.列表初始化 1.1 { } 初始化 1.2 std::initializer_list 2.声明 2.1 auto 2.2 decltype 2.3 nullptr 3. 范围for 4.STL中的一些变化 5.右值引用与移动语义 5.1 左值引用与右值引用 5.2 左值引用与右值引用的比较 5.3 右值引用使用场景 5.4 完美转发 6.新的…

JavaScript事件处理和常用对象

文章目录 前言一、事件处理程序 1.JavaScript 常用事件2.事件处理程序的调用二、常用对象 1.Window 对象2.String 对象3.Date 对象总结 前言 JavaScript 语言是事件驱动型的。这意味着&#xff0c;该门语言可以通过事件触发来调用某一函数或者一段代码。该文还简单介绍了Window…

Android 11 FileProvider的使用和限制

概述&#xff1a; 从Android 7开始&#xff0c;将不允许在app之间&#xff0c;使用file uri,即file://的方式&#xff0c;传递一个file&#xff0c;否则会抛出异常&#xff1a;FileUriExposedException &#xff0c;其解决方案&#xff0c;就是使用FileProvider&#xff0c;用c…

有关 Element-ui 的一些思考

本篇文章是基于 element-ui 的 主题样式修改 曾经为了修改组件风格,一个项目用了上百个样式穿透,后来才发现定制一个主题就够了! 第一步,在官网的主题页面,修改背景色、字体颜色及边框颜色 第二步,下载主题 第三步,用下载的css文件替换掉默认的css文件

如何让Windows控制台窗口不接受鼠标点击(禁用鼠标输入)

一、简述 在我们编写控制台应用程序时&#xff0c;默认情况下程序的打印输出会在控制台窗口中进行显示&#xff0c;我们在写服务功能时在窗口中会不断打印消息输出&#xff0c;这个时候如果使用鼠标点击了控制台窗口&#xff0c;会阻塞程序的继续运行&#xff0c;导致我们的程…

SpringBoot集成Thymeleaf模板引擎,为什么使用(详细介绍)

学习本技术第一件事&#xff1a;你为什么要使用&#xff0c;解决什么问题的&#xff1f; 1.为什么使用&#xff08;使用背景&#xff09;&#xff1f; 首先应用场景是单体项目&#xff0c;如果是前后端分离就不用关注这个了&#xff0c;因为单体项目你前后端都是写在一个项目…

性能小白终于能看懂Jmeter报告了

对于刚接触性能测试的初学者来说&#xff0c;分析JMeter生成的测试报告无疑是一个巨大的挑战。面对大量的数据信息&#xff0c;如何快速理解响应时间、吞吐量、错误率等关键指标&#xff0c;往往让人感到困惑。今天&#xff0c;让我们一起探讨如何轻松看懂JMeter的性能测试报告…

多线程篇(其它容器- CopyOnWriteArrayList)(持续更新迭代)

一、CopyOnWriteArrayList&#xff08;一&#xff09; 1. 简介 并发包中的并发List只有CopyOnWriteArrayList。 CopyOnWriteArrayList是一个线程安全的ArrayList&#xff0c;对其进行的修改操作都是在底层的一个复制的数 组&#xff08;快照&#xff09;上进行的&#xff0…

基于STM32C8T6的CubeMX:HAL库点亮LED

三个可能的问题和解决方法&#xff1a; 大家完成之后回来看&#xff0c;每一种改错误都是一种成长&#xff0c;不要畏惧&#xff0c;要快乐&#xff0c;积极面对&#xff0c;要耐心对待 STMCuBeMX新建项目的两种匪夷所思的问题https://mp.csdn.net/mp_blog/creation/editor/1…

【Android 13源码分析】WindowContainer窗口层级-1-初识窗口层级树

在安卓源码的设计中&#xff0c;将将屏幕分为了37层&#xff0c;不同的窗口将在不同的层级中显示。 对这一块的概念以及相关源码做了详细分析&#xff0c;整理出以下几篇。 【Android 13源码分析】WindowContainer窗口层级-1-初识窗口层级树 【Android 13源码分析】WindowCon…

前端技术(七)——less 教程

一、less简介 1. less是什么&#xff1f; less是一种动态样式语言&#xff0c;属于css预处理器的范畴&#xff0c;它扩展了CSS语言&#xff0c;增加了变量、Mixin、函数等特性&#xff0c;使CSS 更易维护和扩展LESS 既可以在 客户端 上运行 &#xff0c;也可以借助Node.js在服…

Semaphore UI --Ansible webui

1、安装python python下载地址 https://www.python.org/downloads/ 选好版本下载 wget https://www.python.org/ftp/python/3.11.9/Python-3.11.9.tar.xz安装编译工具 sudo dnf groupinstall "Development Tools"安装依赖包 dnf install bzip2-devel ncurses-deve…

IDEA 常用配置和开发插件

件市场中搜索并安装“Git Integration”插件。 一、前言 在本篇文章中我会为大家总结一些我自己常用的配置和开发插件&#xff0c;此外也给大家提供一个建议&#xff0c;可以根据自己的项目需求和个人偏好选择适合的插件。另外&#xff0c;IDEA 也在不断更新&#xff0c;可能会…

哈希表、算法

哈希表 hash&#xff1a; 在编程和数据结构中&#xff0c;"hash" 通常指的是哈希函数&#xff0c;它是一种算法&#xff0c;用于将数据&#xff08;通常是字符 串&#xff09;映射到一个固定大小的数字&#xff08;哈希值&#xff09;。哈希函数在哈希表中尤为重要…

使用vue2+axios+chart.js画折线图 ,出现 RangeError: Maximum call stack size exceeded 错误

目录 效果图 解决方案 修正要点 效果图 修改前App.vue代码&#xff1a; <template><div id"app"><canvas id"myChart"></canvas></div> </template><script> import axios from axios; import { Chart, regis…

stm32 W25Q数据存储

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、cubemx配置二、keil中文件修改与配置三、几个重要函数的说明四、DMA方式传输&#xff08;待写&#xff09;总结 前言 W25Q128 容量为128位 128/8 16 也就…

Mac 上终端使用 MySql 记录

文章目录 下载安装终端进入 MySql常用操作查看数据库选择一个数据库查看当前选择的数据库Navcat 打开提示报错参考文章 下载安装 先下载社区版的 MySql 安装的过程需要设置 root 的密码&#xff0c;这个是要进入数据库所设定的&#xff0c;所以要记住 终端进入 MySql 首先输…

Linux基础-Makefile的编写、以及编写第一个Linux程序:进度条(模拟在 方便下载的同时,更新图形化界面)

目录 一、Linux项目自动化构建工具-make/Makefile ​编辑 背景&#xff1a; makefile小技巧&#xff1a; 二、Linux第一个小程序&#xff0d;进度条 先导&#xff1a; 1.如何利用/r,fflush(stdout)来实现我们想要的效果&#xff1b; 2.写一个倒计时&#xff1a; 进度条…

智能家居环境监测系统设计(论文+源码)

1. 系统方案 系统由9个部分构成&#xff0c;分别是电源模块、烟雾传感器模块、GSM发送短信模块、报警模块、温度传感器模块、人体红外感应模块、按键设置模块、显示模块、MCU模块。各模块的作用如下&#xff1a;电源模块为系统提供电力&#xff1b;烟雾传感器模块检测烟雾浓度&…