From a8e2e2d5c9d658c8eea057d6a1bb12a1627bc9ca Mon Sep 17 00:00:00 2001
From: xiongxiaoyang <773861846@qq.com>
Date: Tue, 24 May 2022 19:53:51 +0800
Subject: [PATCH] =?UTF-8?q?feat:=20=E8=AE=BE=E7=BD=AE=20Elasticsearch=20?=
 =?UTF-8?q?=E6=90=9C=E7=B4=A2=E5=85=B3=E9=94=AE=E8=AF=8D=E9=AB=98=E4=BA=AE?=
 =?UTF-8?q?=E6=98=BE=E7=A4=BA?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../xxyopen/novel/core/constant/EsConsts.java | 110 ++++++++++++++++--
 .../xxyopen/novel/core/task/BookToEsTask.java |   2 +-
 .../service/impl/EsSearchServiceImpl.java     |  33 ++++--
 3 files changed, 126 insertions(+), 19 deletions(-)

diff --git a/src/main/java/io/github/xxyopen/novel/core/constant/EsConsts.java b/src/main/java/io/github/xxyopen/novel/core/constant/EsConsts.java
index d4b9a26..5527098 100644
--- a/src/main/java/io/github/xxyopen/novel/core/constant/EsConsts.java
+++ b/src/main/java/io/github/xxyopen/novel/core/constant/EsConsts.java
@@ -1,7 +1,5 @@
 package io.github.xxyopen.novel.core.constant;
 
-import lombok.Getter;
-
 /**
  * elasticsearch 相关常量
  *
@@ -10,19 +8,109 @@ import lombok.Getter;
  */
 public class EsConsts {
 
+    private EsConsts() {
+        throw new IllegalStateException(SystemConfigConsts.CONST_INSTANCE_EXCEPTION_MSG);
+    }
+
     /**
-     * ES 索引枚举类
-     */
-    @Getter
-    public enum IndexEnum {
+     * 小说索引
+     * */
+    public static class BookIndex{
 
-        BOOK("book");
-
-        IndexEnum(String name) {
-            this.name = name;
+        private BookIndex() {
+            throw new IllegalStateException(SystemConfigConsts.CONST_INSTANCE_EXCEPTION_MSG);
         }
 
-        private String name;
+        /**
+         * 索引名
+         * */
+        public static final String INDEX_NAME = "book";
 
+        /**
+         * id
+         */
+        public static final String FIELD_ID =  "id";
+
+        /**
+         * 作品方向;0-男频 1-女频
+         */
+        public static final String FIELD_WORK_DIRECTION =  "workDirection";
+
+        /**
+         * 类别ID
+         */
+        public static final String FIELD_CATEGORY_ID = "categoryId";
+
+        /**
+         * 类别名
+         */
+        public static final String FIELD_CATEGORY_NAME = "categoryName";
+
+        /**
+         * 小说名
+         */
+        public static final String FIELD_BOOK_NAME = "bookName";
+
+        /**
+         * 作家id
+         */
+        public static final String FIELD_AUTHOR_ID = "authorId";
+
+        /**
+         * 作家名
+         */
+        public static final String FIELD_AUTHOR_NAME = "authorName";
+
+        /**
+         * 书籍描述
+         */
+        public static final String FIELD_BOOK_DESC = "bookDesc";
+
+        /**
+         * 评分;总分:10 ,真实评分 = score/10
+         */
+        public static final String FIELD_SCORE = "score";
+
+        /**
+         * 书籍状态;0-连载中 1-已完结
+         */
+        public static final String FIELD_BOOK_STATUS = "bookStatus";
+
+        /**
+         * 点击量
+         */
+        public static final String FIELD_VISIT_COUNT = "visitCount";
+
+        /**
+         * 总字数
+         */
+        public static final String FIELD_WORD_COUNT = "wordCount";
+
+        /**
+         * 评论数
+         */
+        public static final String FIELD_COMMENT_COUNT = "commentCount";
+
+        /**
+         * 最新章节ID
+         */
+        public static final String FIELD_LAST_CHAPTER_ID = "lastChapterId";
+
+        /**
+         * 最新章节名
+         */
+        public static final String FIELD_LAST_CHAPTER_NAME = "lastChapterName";
+
+        /**
+         * 最新章节更新时间
+         */
+        public static final String FIELD_LAST_CHAPTER_UPDATE_TIME = "lastChapterUpdateTime";
+
+        /**
+         * 是否收费;1-收费 0-免费
+         */
+        public static final String FIELD_IS_VIP = "isVip";
+        
     }
+
 }
diff --git a/src/main/java/io/github/xxyopen/novel/core/task/BookToEsTask.java b/src/main/java/io/github/xxyopen/novel/core/task/BookToEsTask.java
index 4a64be1..23ef4d9 100644
--- a/src/main/java/io/github/xxyopen/novel/core/task/BookToEsTask.java
+++ b/src/main/java/io/github/xxyopen/novel/core/task/BookToEsTask.java
@@ -63,7 +63,7 @@ public class BookToEsTask {
                 EsBookDto esBook = buildEsBook(book);
                 br.operations(op -> op
                         .index(idx -> idx
-                                .index(EsConsts.IndexEnum.BOOK.getName())
+                                .index(EsConsts.BookIndex.INDEX_NAME)
                                 .id(book.getId().toString())
                                 .document(esBook)
                         )
diff --git a/src/main/java/io/github/xxyopen/novel/service/impl/EsSearchServiceImpl.java b/src/main/java/io/github/xxyopen/novel/service/impl/EsSearchServiceImpl.java
index c0eb606..b03dcb8 100644
--- a/src/main/java/io/github/xxyopen/novel/service/impl/EsSearchServiceImpl.java
+++ b/src/main/java/io/github/xxyopen/novel/service/impl/EsSearchServiceImpl.java
@@ -10,6 +10,7 @@ import co.elastic.clients.elasticsearch.core.SearchResponse;
 import co.elastic.clients.elasticsearch.core.search.Hit;
 import co.elastic.clients.elasticsearch.core.search.TotalHits;
 import co.elastic.clients.json.JsonData;
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.baomidou.mybatisplus.core.toolkit.StringUtils;
 import io.github.xxyopen.novel.core.common.resp.PageRespDto;
 import io.github.xxyopen.novel.core.common.resp.RestResp;
@@ -48,7 +49,8 @@ public class EsSearchServiceImpl implements SearchService {
 
         SearchResponse<EsBookDto> response = esClient.search(s -> {
 
-                    SearchRequest.Builder searchBuilder = s.index(EsConsts.IndexEnum.BOOK.getName());
+                    SearchRequest.Builder searchBuilder = s.index(EsConsts.BookIndex.INDEX_NAME);
+                    // 构建检索条件
                     buildSearchCondition(condition, searchBuilder);
                     // 排序
                     if (!StringUtils.isBlank(condition.getSort())) {
@@ -61,6 +63,11 @@ public class EsSearchServiceImpl implements SearchService {
                     // 分页
                     searchBuilder.from((condition.getPageNum() - 1) * condition.getPageSize())
                             .size(condition.getPageSize());
+                    // 设置高亮显示
+                    searchBuilder.highlight(h -> h.fields(EsConsts.BookIndex.FIELD_BOOK_NAME
+                                    , t -> t.preTags("<em style='color:red'>").postTags("</em>"))
+                            .fields(EsConsts.BookIndex.FIELD_AUTHOR_NAME
+                                    , t -> t.preTags("<em style='color:red'>").postTags("</em>")));
 
                     return searchBuilder;
                 },
@@ -74,6 +81,12 @@ public class EsSearchServiceImpl implements SearchService {
         for (Hit<EsBookDto> hit : hits) {
             EsBookDto book = hit.source();
             assert book != null;
+            if (!CollectionUtils.isEmpty(hit.highlight().get(EsConsts.BookIndex.FIELD_BOOK_NAME))) {
+                book.setBookName(hit.highlight().get(EsConsts.BookIndex.FIELD_BOOK_NAME).get(0));
+            }
+            if (!CollectionUtils.isEmpty(hit.highlight().get(EsConsts.BookIndex.FIELD_AUTHOR_NAME))) {
+                book.setAuthorName(hit.highlight().get(EsConsts.BookIndex.FIELD_AUTHOR_NAME).get(0));
+            }
             list.add(BookInfoRespDto.builder()
                     .id(book.getId())
                     .bookName(book.getBookName())
@@ -87,8 +100,12 @@ public class EsSearchServiceImpl implements SearchService {
         }
         assert total != null;
         return RestResp.ok(PageRespDto.of(condition.getPageNum(), condition.getPageSize(), total.value(), list));
+
     }
 
+    /**
+     * 构建检索条件
+     */
     private void buildSearchCondition(BookSearchReqDto condition, SearchRequest.Builder searchBuilder) {
 
         BoolQuery boolQuery = BoolQuery.of(b -> {
@@ -96,7 +113,9 @@ public class EsSearchServiceImpl implements SearchService {
             if (!StringUtils.isBlank(condition.getKeyword())) {
                 // 关键词匹配
                 b.must((q -> q.multiMatch(t -> t
-                        .fields("bookName^2","authorName^1.8","bookDesc^0.1")
+                        .fields(EsConsts.BookIndex.FIELD_BOOK_NAME + "^2"
+                                , EsConsts.BookIndex.FIELD_AUTHOR_NAME + "^1.8"
+                                , EsConsts.BookIndex.FIELD_BOOK_DESC + "^0.1")
                         .query(condition.getKeyword())
                 )
                 ));
@@ -105,14 +124,14 @@ public class EsSearchServiceImpl implements SearchService {
             // 精确查询
             if (Objects.nonNull(condition.getWorkDirection())) {
                 b.must(TermQuery.of(m -> m
-                        .field("workDirection")
+                        .field(EsConsts.BookIndex.FIELD_WORK_DIRECTION)
                         .value(condition.getWorkDirection())
                 )._toQuery());
             }
 
             if (Objects.nonNull(condition.getCategoryId())) {
                 b.must(TermQuery.of(m -> m
-                        .field("categoryId")
+                        .field(EsConsts.BookIndex.FIELD_CATEGORY_ID)
                         .value(condition.getCategoryId())
                 )._toQuery());
             }
@@ -120,21 +139,21 @@ public class EsSearchServiceImpl implements SearchService {
             // 范围查询
             if (Objects.nonNull(condition.getWordCountMin())) {
                 b.must(RangeQuery.of(m -> m
-                        .field("wordCount")
+                        .field(EsConsts.BookIndex.FIELD_WORD_COUNT)
                         .gte(JsonData.of(condition.getWordCountMin()))
                 )._toQuery());
             }
 
             if (Objects.nonNull(condition.getWordCountMax())) {
                 b.must(RangeQuery.of(m -> m
-                        .field("wordCount")
+                        .field(EsConsts.BookIndex.FIELD_WORD_COUNT)
                         .lt(JsonData.of(condition.getWordCountMax()))
                 )._toQuery());
             }
 
             if (Objects.nonNull(condition.getUpdateTimeMin())) {
                 b.must(RangeQuery.of(m -> m
-                        .field("lastChapterUpdateTime")
+                        .field(EsConsts.BookIndex.FIELD_LAST_CHAPTER_UPDATE_TIME)
                         .gte(JsonData.of(condition.getUpdateTimeMin().getTime()))
                 )._toQuery());
             }