日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

【牛客讨论区】第六章:Elasticsearch

發(fā)布時(shí)間:2023/12/29 编程问答 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【牛客讨论区】第六章:Elasticsearch 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

目錄

  • 1. Elasticsearch入門(mén)
  • 2. Spring整合Elasticsearch
    • 2.1 springboot 版本問(wèn)題
    • 2.2 整合Elasticsearch
  • 3. 開(kāi)發(fā)社區(qū)搜索功能

1. Elasticsearch入門(mén)

Elasticsearch簡(jiǎn)介

  • 一個(gè)分布式的、Restful風(fēng)格的搜索引擎。
  • 支持對(duì)各種類(lèi)型的數(shù)據(jù)的檢索。
  • 搜索速度快,可以提供實(shí)時(shí)的搜索服務(wù)。
  • 便于水平擴(kuò)展,每秒可以處理PB級(jí)海量數(shù)據(jù)。

Elasticsearch術(shù)語(yǔ)

  • 索引、類(lèi)型、文檔、字段。
  • 集群、節(jié)點(diǎn)、分片、副本。

https://www.elastic.co
https://www.getpostman.com

【安裝】
解壓 elasticsearch-6.4.3.zip 即可

【修改配置文件 】
E:\elasticsearch-6.4.3\config 下的 elasticsearch.yml

17行

cluster.name: nowcoder

33行

path.data: d:\work\data\elasticsearch-6.4.3\data

37行

path.logs: d:\work\data\elasticsearch-6.4.3\logs

【配置環(huán)境變量】

將 bin 目錄 E:\elasticsearch-6.4.3\bin 配到 path 中

【安裝中文分詞插件】
注意:必須將elasticsearch-analysis-ik-6.4.3.zip 解壓到固定的目錄下
E:\elasticsearch-6.4.3\plugins 下新建 ik 目錄,解壓到 ik 目錄下即可

【安裝postman】

【啟動(dòng) elasticsearch】
Windows下,雙擊 E:\elasticsearch-6.4.3\bin 下的 elasticsearch.bat

打開(kāi)一個(gè) cmd,訪問(wèn) elasticsearch 健康狀況

curl -X GET "localhost:9200/_cat/health?v"

查看節(jié)點(diǎn)

curl -X GET "localhost:9200/_cat/nodes?v"

查看索引

curl -X GET "localhost:9200/_cat/indices?v"

創(chuàng)建索引

curl -X PUT "localhost:9200/test"

刪除索引

curl -X DELETE "localhost:9200/test"

【使用 postman 訪問(wèn) es】

發(fā)送 GET 請(qǐng)求:查看索引
localhost:9200/_cat/indices?v

發(fā)送 PUT 請(qǐng)求:建立索引
localhost:9200/test


發(fā)送 DELETE 請(qǐng)求:刪除索引
localhost:9200/test

【向 es 提交數(shù)據(jù)】
test 是索引,也是表名,不存在的話會(huì)自動(dòng)創(chuàng)建,_doc是占位的,1是 id,在 body 中寫(xiě)數(shù)據(jù),以 JSON 方式傳輸

{"title":"hello","content":"How are you" }

點(diǎn)擊 send,返回結(jié)果:

{"_index": "test","_type": "_doc","_id": "1","_version": 1,"result": "created","_shards": {"total": 2,"successful": 1,"failed": 0},"_seq_no": 0,"_primary_term": 1 }

【查看該條數(shù)據(jù)】
發(fā)送 GET 請(qǐng)求:localhost:9200/test/_doc/1

【刪除該數(shù)據(jù)】
發(fā)送 DELETE 請(qǐng)求:localhost:9200/test/_doc/1

【實(shí)現(xiàn)搜索】
先提交幾條數(shù)據(jù)

PUT : localhost:9200/test/_doc/1

{"title":"互聯(lián)網(wǎng)求職","content":"尋求一份運(yùn)維的崗位" }

PUT : localhost:9200/test/_doc/2

{"title":"互聯(lián)網(wǎng)招聘","content":"招一名資深程序員" }

PUT : localhost:9200/test/_doc/3

{"title":"實(shí)習(xí)生推薦","content":"本人在一家互聯(lián)網(wǎng)公司任職,可推薦實(shí)習(xí)開(kāi)發(fā)崗位!" }

搜索:

不加條件的搜索
GET:localhost:9200/test/_search
加條件的搜索
GET:localhost:9200/test/_search?q=title:互聯(lián)網(wǎng)

localhost:9200/test/_search?q=content:運(yùn)維實(shí)習(xí)

搜索引擎會(huì)將 “運(yùn)維實(shí)習(xí)” 分詞成 “運(yùn)維”和 “實(shí)習(xí)”,分別去搜索。

【更加復(fù)雜的搜索】
地址欄寫(xiě)不下,可以在 body 中寫(xiě),fields 表示要在哪些字段中進(jìn)行搜索

{"query":{"multi_match":{"query":"互聯(lián)網(wǎng)","fields":["title","content"]}} }

2. Spring整合Elasticsearch

2.1 springboot 版本問(wèn)題

【問(wèn)題】
我的 springboot 版本是 2.3.7.RELEASE,需要降到 2.1.5.RELEASE,不然和 Elasticsearch 版本不兼容,會(huì)產(chǎn)生一系列的問(wèn)題
【解決】
將 pom.xml 中所有的 2.3.7.RELEASE 都改成 2.1.5.RELEASE,然后點(diǎn)擊IDEA 的 “File”–“Invalidate Caches” ,重新啟動(dòng)即可

2.2 整合Elasticsearch

pom.xml

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-elasticsearch</artifactId> </dependency>

application.properties

# ElasticsearchProperties spring.data.elasticsearch.cluster-name=nowcoder spring.data.elasticsearch.cluster-nodes=127.0.0.1:9300

【解決沖突】
Redis 和 elasticsearch 底層都是基于 Netty,所以二者啟動(dòng)時(shí)會(huì)有沖突,解決如下:

CommunityApplication 類(lèi)的 main 方法之前寫(xiě)個(gè)方法

@PostConstruct public void init() {//解決Netty啟動(dòng)沖突//詳見(jiàn) Netty4Utils 類(lèi),設(shè)置為falseSystem.setProperty("es.set.netty.runtime.available.processors", "false"); }

因?yàn)槲覀兪菍⑻哟娴?es 中實(shí)現(xiàn)搜索功能,所以需要通過(guò)注解配置一下 DiscussPost 類(lèi)

@Document(indexName = "discusspost", type = "_doc", shards = 6, replicas = 3) public class DiscussPost {@Idprivate int id;@Field(type = FieldType.Integer)private int userId;//analyzer:存儲(chǔ)分詞器,searchAnalyzer:搜索分詞器@Field(type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_smart")private String title;@Field(type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_smart")private String content;@Field(type = FieldType.Integer)private int type;@Field(type = FieldType.Integer)private int status;@Field(type = FieldType.Date)private Date createTime;@Field(type = FieldType.Integer)private int commentCount;@Field(type = FieldType.Double)private double score;

dao 包下新建子包 elasticsearch
新建接口

package com.nowcoder.community.dao.elasticsearch;import com.nowcoder.community.entity.DiscussPost; import org.springframework.data.elasticsearch.repository.ElasticsearchRepository; import org.springframework.stereotype.Repository;@Repository //Mapper注解是Mybatis的,這個(gè)類(lèi)不需要Mybatis,所以用Repository public interface DiscussPostRepository extends ElasticsearchRepository<DiscussPost, Integer> {//spring會(huì)自動(dòng)實(shí)現(xiàn)ElasticsearchRepository中的增刪改查,現(xiàn)在就可以使用es了 }

新建測(cè)試類(lèi)

最終版

package com.nowcoder.community;import com.nowcoder.community.dao.DiscussPostMapper; import com.nowcoder.community.dao.elasticsearch.DiscussPostRepository; import com.nowcoder.community.entity.DiscussPost; import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.search.SearchHit; import org.elasticsearch.search.SearchHits; import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder; import org.elasticsearch.search.fetch.subphase.highlight.HighlightField; import org.elasticsearch.search.sort.SortBuilders; import org.elasticsearch.search.sort.SortOrder; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.data.elasticsearch.core.ElasticsearchTemplate; import org.springframework.data.elasticsearch.core.SearchResultMapper; import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage; import org.springframework.data.elasticsearch.core.aggregation.impl.AggregatedPageImpl; import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder; import org.springframework.data.elasticsearch.core.query.SearchQuery; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringRunner;import javax.annotation.Resource; import java.util.ArrayList; import java.util.Date; import java.util.List;@RunWith(SpringRunner.class) @SpringBootTest @ContextConfiguration(classes = CommunityApplication.class) public class ElasticsearchTests {@Resourceprivate DiscussPostMapper discussPostMapper;@Resourceprivate DiscussPostRepository discussPostRepository;//DiscussPostRepository 功能有限,因此還需要 ElasticsearchTemplate@Resourceprivate ElasticsearchTemplate elasticTemplate;@Testpublic void testInsert() { //插入一條數(shù)據(jù)discussPostRepository.save(discussPostMapper.selectDiscussById(241));discussPostRepository.save(discussPostMapper.selectDiscussById(242));discussPostRepository.save(discussPostMapper.selectDiscussById(243));}@Testpublic void testInsertList() { //插入多條數(shù)據(jù)。為后面的搜索功能做準(zhǔn)備discussPostRepository.saveAll(discussPostMapper.selectDiscussPosts(101, 0, 100));discussPostRepository.saveAll(discussPostMapper.selectDiscussPosts(102, 0, 100));discussPostRepository.saveAll(discussPostMapper.selectDiscussPosts(103, 0, 100));discussPostRepository.saveAll(discussPostMapper.selectDiscussPosts(112, 0, 100));discussPostRepository.saveAll(discussPostMapper.selectDiscussPosts(131, 0, 100));discussPostRepository.saveAll(discussPostMapper.selectDiscussPosts(132, 0, 100));discussPostRepository.saveAll(discussPostMapper.selectDiscussPosts(133, 0, 100));discussPostRepository.saveAll(discussPostMapper.selectDiscussPosts(134, 0, 100));}@Testpublic void testUpdate() { //所謂修改就是save一下,覆蓋原來(lái)的DiscussPost post = discussPostMapper.selectDiscussById(231);post.setContent("我是新人,使勁灌水...");discussPostRepository.save(post);}@Testpublic void testDelete() {discussPostRepository.deleteById(231); //刪一條數(shù)據(jù)//discussPostRepository.deleteAll();//刪除所有數(shù)據(jù)}@Testpublic void testSearchByRepository() {SearchQuery searchQuery = new NativeSearchQueryBuilder()//搜索條件 從title和content中搜 互聯(lián)網(wǎng)寒冬.withQuery(QueryBuilders.multiMatchQuery("互聯(lián)網(wǎng)寒冬", "title", "content"))//排序條件.withSort(SortBuilders.fieldSort("type").order(SortOrder.DESC)) //優(yōu)先按照type降序.withSort(SortBuilders.fieldSort("score").order(SortOrder.DESC)).withSort(SortBuilders.fieldSort("createTime").order(SortOrder.DESC)).withPageable(PageRequest.of(0, 10)).withHighlightFields(new HighlightBuilder.Field("title").preTags("<em>").postTags("</em>"),new HighlightBuilder.Field("content").preTags("<em>").postTags("</em>")).build();//底層獲取到了高亮顯示的值,但是沒(méi)有返回Page<DiscussPost> page = discussPostRepository.search(searchQuery);System.out.println(page.getTotalElements());System.out.println(page.getTotalPages());System.out.println(page.getNumber());System.out.println(page.getSize());for (DiscussPost post : page) {System.out.println(post);}}@Testpublic void testSearchByTemplate() {SearchQuery searchQuery = new NativeSearchQueryBuilder()//搜索條件 從title和content中搜 互聯(lián)網(wǎng)寒冬.withQuery(QueryBuilders.multiMatchQuery("互聯(lián)網(wǎng)寒冬", "title", "content"))//排序條件.withSort(SortBuilders.fieldSort("type").order(SortOrder.DESC)) //優(yōu)先按照type降序.withSort(SortBuilders.fieldSort("score").order(SortOrder.DESC)).withSort(SortBuilders.fieldSort("createTime").order(SortOrder.DESC)).withPageable(PageRequest.of(0, 10)).withHighlightFields(new HighlightBuilder.Field("title").preTags("<em>").postTags("</em>"),new HighlightBuilder.Field("content").preTags("<em>").postTags("</em>")).build();Page<DiscussPost> page = elasticTemplate.queryForPage(searchQuery, DiscussPost.class, new SearchResultMapper() {@Overridepublic <T> AggregatedPage<T> mapResults(SearchResponse response, Class<T> aClass, Pageable pageable) {SearchHits hits = response.getHits();if (hits.getTotalHits() <= 0) {return null;}List<DiscussPost> list = new ArrayList<>();for (SearchHit hit : hits) {DiscussPost post = new DiscussPost();String id = hit.getSourceAsMap().get("id").toString();post.setId(Integer.valueOf(id));String userId = hit.getSourceAsMap().get("userId").toString();post.setUserId(Integer.valueOf(userId));String title = hit.getSourceAsMap().get("title").toString();post.setTitle(title);String content = hit.getSourceAsMap().get("content").toString();post.setContent(content);String status = hit.getSourceAsMap().get("status").toString();post.setStatus(Integer.valueOf(status));String createTime = hit.getSourceAsMap().get("createTime").toString();post.setCreateTime(new Date(Long.valueOf(createTime)));String commentCount = hit.getSourceAsMap().get("commentCount").toString();post.setCommentCount(Integer.valueOf(commentCount));//處理高亮顯示的結(jié)果HighlightField titleField = hit.getHighlightFields().get("title");if (titleField != null) {post.setTitle(titleField.getFragments()[0].toString());}HighlightField contentField = hit.getHighlightFields().get("content");if (contentField != null) {post.setContent(contentField.getFragments()[0].toString());}list.add(post);}return new AggregatedPageImpl(list, pageable,hits.getTotalHits(), response.getAggregations(),response.getScrollId(), hits.getMaxScore());}});System.out.println(page.getTotalElements());System.out.println(page.getTotalPages());System.out.println(page.getNumber());System.out.println(page.getSize());for (DiscussPost post : page) {System.out.println(post);}} }

啟動(dòng) zookeeper、kafka、Elasticsearch,執(zhí)行測(cè)試方法 testInsert()

【踩坑】
這里執(zhí)行了好多次,每次都出現(xiàn) java: 程序包org.junit.jupiter.api不存在

原因是我們降低 springboot 版本之后,Junit 的版本也由 5 降低為 4,org.junit.jupiter.api 是 Junit5 的,自然就找不到了,所以我們需要按照 Junit4 的語(yǔ)法進(jìn)行測(cè)試,org.junit.Test 是Junit4 的包

方法:
將所有測(cè)試類(lèi)中的 import org.junit.jupiter.api.Test; 改成 import org.junit.Test;在所有測(cè)試類(lèi)的類(lèi)名前寫(xiě)這三個(gè)注解(BlockingQueueTests不用管,因?yàn)樗怯胢ain方法測(cè)試的)

@RunWith(SpringRunner.class) @SpringBootTest @ContextConfiguration(classes = CommunityApplication.class)

如果還有錯(cuò),重啟一下 elasticsearch

使用 postman 查看是否插入成功:


3. 開(kāi)發(fā)社區(qū)搜索功能

搜索服務(wù)

  • 將帖子保存至Elasticsearch服務(wù)器。
  • 從Elasticsearch服務(wù)器刪除帖子。
  • 從Elasticsearch服務(wù)器搜索帖子。

發(fā)布事件

  • 發(fā)布帖子時(shí),將帖子異步的提交到Elasticsearch服務(wù)器。
  • 增加評(píng)論時(shí),將帖子異步的提交到Elasticsearch服務(wù)器。
  • 在消費(fèi)組件中增加一個(gè)方法,消費(fèi)帖子發(fā)布事件。

顯示結(jié)果

  • 在控制器中處理搜索請(qǐng)求,在HTML上顯示搜索結(jié)果。

解決一個(gè)遺漏的小問(wèn)題:
discusspost-mapper.xml,加上 keyProperty

<insert id="insertDiscussPost" parameterType="DiscussPost" keyProperty="id">insert into discuss_post (<include refid="insertFields"></include>)values (#{userId}, #{title}, #{content}, #{type}, #{status}, #{createTime}, #{commentCount}, #{score}) </insert>

service層

package com.nowcoder.community.service;import com.nowcoder.community.dao.elasticsearch.DiscussPostRepository; import com.nowcoder.community.entity.DiscussPost; import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.search.SearchHit; import org.elasticsearch.search.SearchHits; import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder; import org.elasticsearch.search.fetch.subphase.highlight.HighlightField; import org.elasticsearch.search.sort.SortBuilders; import org.elasticsearch.search.sort.SortOrder; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.data.elasticsearch.core.ElasticsearchTemplate; import org.springframework.data.elasticsearch.core.SearchResultMapper; import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage; import org.springframework.data.elasticsearch.core.aggregation.impl.AggregatedPageImpl; import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder; import org.springframework.data.elasticsearch.core.query.SearchQuery; import org.springframework.stereotype.Service;import javax.annotation.Resource; import java.util.ArrayList; import java.util.Date; import java.util.List;@Service public class ElasticsearchService {@Resourceprivate DiscussPostRepository discussRepository;@Resourceprivate ElasticsearchTemplate elasticTemplate;public void saveDiscussPost(DiscussPost post) {discussRepository.save(post);}public void deleteDiscussPost(int id) {discussRepository.deleteById(id);}public Page<DiscussPost> searchDiscussPost(String keyword, int current, int limit) {SearchQuery searchQuery = new NativeSearchQueryBuilder()//搜索條件 從title和content中搜 互聯(lián)網(wǎng)寒冬.withQuery(QueryBuilders.multiMatchQuery(keyword, "title", "content"))//排序條件.withSort(SortBuilders.fieldSort("type").order(SortOrder.DESC)) //優(yōu)先按照type降序.withSort(SortBuilders.fieldSort("score").order(SortOrder.DESC)).withSort(SortBuilders.fieldSort("createTime").order(SortOrder.DESC)).withPageable(PageRequest.of(current, limit)).withHighlightFields(new HighlightBuilder.Field("title").preTags("<em>").postTags("</em>"),new HighlightBuilder.Field("content").preTags("<em>").postTags("</em>")).build();return elasticTemplate.queryForPage(searchQuery, DiscussPost.class, new SearchResultMapper() {@Overridepublic <T> AggregatedPage<T> mapResults(SearchResponse response, Class<T> aClass, Pageable pageable) {SearchHits hits = response.getHits();if (hits.getTotalHits() <= 0) {return null;}List<DiscussPost> list = new ArrayList<>();for (SearchHit hit : hits) {DiscussPost post = new DiscussPost();String id = hit.getSourceAsMap().get("id").toString();post.setId(Integer.valueOf(id));String userId = hit.getSourceAsMap().get("userId").toString();post.setUserId(Integer.valueOf(userId));String title = hit.getSourceAsMap().get("title").toString();post.setTitle(title);String content = hit.getSourceAsMap().get("content").toString();post.setContent(content);String status = hit.getSourceAsMap().get("status").toString();post.setStatus(Integer.valueOf(status));String createTime = hit.getSourceAsMap().get("createTime").toString();post.setCreateTime(new Date(Long.valueOf(createTime)));String commentCount = hit.getSourceAsMap().get("commentCount").toString();post.setCommentCount(Integer.valueOf(commentCount));//處理高亮顯示的結(jié)果HighlightField titleField = hit.getHighlightFields().get("title");if (titleField != null) {post.setTitle(titleField.getFragments()[0].toString());}HighlightField contentField = hit.getHighlightFields().get("content");if (contentField != null) {post.setContent(contentField.getFragments()[0].toString());}list.add(post);}return new AggregatedPageImpl(list, pageable,hits.getTotalHits(), response.getAggregations(),response.getScrollId(), hits.getMaxScore());}});}}

controller 層

CommunityConstant
新增常量

//主題:發(fā)帖 String TOPIC_PUBLISH = "publish";

DiscussPostController 完善 addDiscussPost() 方法

@Resource private EventProducer eventProducer;@PostMapping("/add") @ResponseBody public String addDiscussPost(String title, String content) {User user = hostHolder.getUser();if (user == null) {return CommunityUtil.getJSONString(403, "你還沒(méi)有登錄哦!");}DiscussPost discussPost = new DiscussPost();discussPost.setUserId(user.getId());discussPost.setTitle(title);discussPost.setContent(content);discussPost.setCreateTime(new Date());discussPostService.addDiscussPost(discussPost);//觸發(fā)發(fā)帖事件Event event = new Event().setTopic(TOPIC_PUBLISH).setUserId(user.getId()).setEntityType(ENTITY_TYPE_POST).setEntityId(discussPost.getId());eventProducer.fireEvent(event);//報(bào)錯(cuò)的情況,將來(lái)統(tǒng)一處理return CommunityUtil.getJSONString(0, "發(fā)布成功!"); }

CommentController
addComment 方法,在 return 之前,加一段邏輯:
某個(gè)帖子新增評(píng)論之后,需要重新上傳 es 服務(wù)器,覆蓋掉舊的帖子

if (comment.getEntityType() == ENTITY_TYPE_POST) {event = new Event().setTopic(TOPIC_PUBLISH).setUserId(comment.getUserId()).setEntityType(ENTITY_TYPE_POST).setEntityId(discussPostId);eventProducer.fireEvent(event); }

EventConsumer

增加方法

@Resource private DiscussPostService discussPostService;@Resource private ElasticsearchService elasticsearchService;//消費(fèi)發(fā)帖事件 @KafkaListener(topics = {TOPIC_PUBLISH}) public void handlePublishMessage(ConsumerRecord record) {if (record == null || record.value() == null) {logger.error("消息的內(nèi)容為空!");return;}Event event = JSONObject.parseObject(record.value().toString(), Event.class);if (event == null) {logger.error("消息格式錯(cuò)誤!");return;}DiscussPost post = discussPostService.findDiscussPostById(event.getEntityId());elasticsearchService.saveDiscussPost(post); }

新建controller

package com.nowcoder.community.controller;import com.nowcoder.community.entity.DiscussPost; import com.nowcoder.community.entity.Page; import com.nowcoder.community.service.ElasticsearchService; import com.nowcoder.community.service.LikeService; import com.nowcoder.community.service.UserService; import com.nowcoder.community.util.CommunityConstant; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping;import javax.annotation.Resource; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map;@Controller public class SearchController implements CommunityConstant {@Resourceprivate ElasticsearchService elasticsearchService;@Resourceprivate UserService userService;@Resourceprivate LikeService likeService;//格式 search?keyword=xxx@GetMapping("/search")public String search(String keyword, Page page, Model model) {//搜索帖子org.springframework.data.domain.Page<DiscussPost> searchResult =elasticsearchService.searchDiscussPost(keyword, page.getCurrent() - 1, page.getLimit());//聚合數(shù)據(jù)List<Map<String, Object>> discussPosts = new ArrayList<>();if (searchResult != null) {for (DiscussPost post : searchResult) {Map<String, Object> map = new HashMap<>();//帖子map.put("post", post);//作者map.put("user", userService.findUserById(post.getUserId()));//點(diǎn)贊數(shù)量map.put("likeCount", likeService.findEntityLikeCount(ENTITY_TYPE_POST, post.getId()));discussPosts.add(map);}}model.addAttribute("discussPosts", discussPosts);model.addAttribute("keyword", keyword);//分頁(yè)page.setPath("/search?keyword=" + keyword);page.setRows(searchResult == null ? 0 : (int) searchResult.getTotalElements());return "/site/search";} }

index.html

52行 form 表單

<!-- 搜索 --> <form class="form-inline my-2 my-lg-0" method="get" th:action="@{/search}"><input class="form-control mr-sm-2" type="search" aria-label="Search" name="keyword" th:value="${keyword}"/><button class="btn btn-outline-light my-2 my-sm-0" type="submit">搜索</button> </form>

search.html
2行

<html lang="en" xmlns:th="http://www.thymeleaf.org">

8行

<link rel="stylesheet" th:href="@{/css/global.css}" />

14行

<header class="bg-dark sticky-top" th:replace="index::header">

刪除 86-161 的 li 標(biāo)簽,留一個(gè) li 即可

170行

<script th:src="@{/js/global.js}"></script>

67行

<li class="media pb-3 pt-3 mb-3 border-bottom" th:each="map:${discussPosts}">

68行

<img th:src="${map.user.headerUrl}" class="mr-4 rounded-circle" alt="用戶頭像" style="width: 50px;height: 50px;">

71行

<a th:href="@{|/discuss/detail/${map.post.id}|}" th:utext="${map.post.title}">備戰(zhàn)<em>春招</em>,面試刷題跟他復(fù)習(xí),一個(gè)月全搞定!</a>

73行

<div class="mb-3" th:utext="${map.post.content}">

77行

<u class="mr-3" th:utext="${map.user.username}">寒江雪</u> 發(fā)布于 <b th:text="${#dates.format(map.post.createTime, 'yyyy-MM-dd HH:mm:ss')}">2019-04-15 15:32:18</b>

80行

<li class="d-inline ml-2"><i th:text="${map.likeCount}">11</i></li>

82行

<li class="d-inline ml-2">回復(fù) <i th:text="${map.post.commentCount}">7</i></li>

89行

<!-- 分頁(yè) --> <nav class="mt-5" th:replace="index::pagination">

測(cè)試:

登錄賬號(hào),新發(fā)一個(gè)帖子,看看能不能搜到。

總結(jié)

以上是生活随笔為你收集整理的【牛客讨论区】第六章:Elasticsearch的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。