亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > Java > 正文

Spring Boot2.0整合ES5實現文章內容搜索實戰

2024-07-13 10:15:52
字體:
來源:轉載
供稿:網友

一、文章內容搜索思路

上一篇講了在怎么在 Spring Boot 2.0 上整合 ES 5 ,這一篇聊聊具體實戰。簡單講下如何實現文章、問答這些內容搜索的具體實現。實現思路很簡單:

  1. 基于「短語匹配」并設置最小匹配權重值
  2. 哪來的短語,利用 IK 分詞器分詞
  3. 基于 Fiter 實現篩選
  4. 基于 Pageable 實現分頁排序

這里直接調用搜索的話,容易搜出不盡人意的東西。因為內容搜索關注內容的連接性。所以這里處理方法比較 low ,希望多交流一起實現更好的搜索方法。就是通過分詞得到很多短語,然后利用短語進行短語精準匹配。

ES 安裝 IK 分詞器插件很簡單。第一步,在下載對應版本 https://github.com/medcl/elasticsearch-analysis-ik/releases。第二步,在 elasticsearch-5.5.3/plugins 目錄下,新建一個文件夾 ik,把 elasticsearch-analysis-ik-5.5.3.zip 解壓后的文件拷貝到 elasticsearch-5.1.1/plugins/ik 目錄下。最后重啟 ES 即可。

二、搜索內容分詞

安裝好 IK ,如何調用呢?

第一步,我這邊搜搜內容會以 逗號 拼接傳入。所以會先將逗號分割

第二步,在搜索詞中加入自己本身,因為有些詞經過 ik 分詞后就沒了... 這是個 bug

第三步,利用 AnalyzeRequestBuilder 對象獲取 IK 分詞后的返回值對象列表

第四步,優化分詞結果,比如都為詞,則保留全部;有詞有字,則保留詞;只有字,則保留字

核心實現代碼如下:

  /**   * 搜索內容分詞   */  protected List<String> handlingSearchContent(String searchContent) {    List<String> searchTermResultList = new ArrayList<>();    // 按逗號分割,獲取搜索詞列表    List<String> searchTermList = Arrays.asList(searchContent.split(SearchConstant.STRING_TOKEN_SPLIT));    // 如果搜索詞大于 1 個字,則經過 IK 分詞器獲取分詞結果列表    searchTermList.forEach(searchTerm -> {      // 搜索詞 TAG 本身加入搜索詞列表,并解決 will 這種問題      searchTermResultList.add(searchTerm);      // 獲取搜索詞 IK 分詞列表      searchTermResultList.addAll(getIkAnalyzeSearchTerms(searchTerm));    });    return searchTermResultList;  }  /**   * 調用 ES 獲取 IK 分詞后結果   */  protected List<String> getIkAnalyzeSearchTerms(String searchContent) {    AnalyzeRequestBuilder ikRequest = new AnalyzeRequestBuilder(elasticsearchTemplate.getClient(),        AnalyzeAction.INSTANCE, SearchConstant.INDEX_NAME, searchContent);    ikRequest.setTokenizer(SearchConstant.TOKENIZER_IK_MAX);    List<AnalyzeResponse.AnalyzeToken> ikTokenList = ikRequest.execute().actionGet().getTokens();    // 循環賦值    List<String> searchTermList = new ArrayList<>();    ikTokenList.forEach(ikToken -> {      searchTermList.add(ikToken.getTerm());    });    return handlingIkResultTerms(searchTermList);  }  /**   * 如果分詞結果:洗發水(洗發、發水、洗、發、水)   * - 均為詞,保留   * - 詞 + 字,只保留詞   * - 均為字,保留字   */  private List<String> handlingIkResultTerms(List<String> searchTermList) {    Boolean isPhrase = false;    Boolean isWord = false;    for (String term : searchTermList) {      if (term.length() > SearchConstant.SEARCH_TERM_LENGTH) {        isPhrase = true;      } else {        isWord = true;      }    }    if (isWord & isPhrase) {      List<String> phraseList = new ArrayList<>();      searchTermList.forEach(term -> {        if (term.length() > SearchConstant.SEARCH_TERM_LENGTH) {          phraseList.add(term);        }      });      return phraseList;    }    return searchTermList;  }

三、搜索查詢語句

構造內容枚舉對象,羅列需要搜索的字段,ContentSearchTermEnum 代碼如下:

import lombok.AllArgsConstructor;@AllArgsConstructorpublic enum ContentSearchTermEnum {  // 標題  TITLE("title"),  // 內容  CONTENT("content");  /**   * 搜索字段   */  private String name;  public String getName() {    return name;  }  public void setName(String name) {    this.name = name;  }}

循環進行「短語搜索匹配」搜索字段,然后并設置最低權重值為 1。核心代碼如下:

  /**   * 構造查詢條件   */  private void buildMatchQuery(BoolQueryBuilder queryBuilder, List<String> searchTermList) {    for (String searchTerm : searchTermList) {      for (ContentSearchTermEnum searchTermEnum : ContentSearchTermEnum.values()) {        queryBuilder.should(QueryBuilders.matchPhraseQuery(searchTermEnum.getName(), searchTerm));      }    }    queryBuilder.minimumShouldMatch(SearchConstant.MINIMUM_SHOULD_MATCH);  }

四、篩選條件

搜到東西不止,有時候需求是這樣的。需要在某個品類下搜索,比如電商需要在某個 品牌 下搜索商品。那么需要構造一些 fitler 進行篩選。對應 SQL 語句的 Where 下的 OR 和 AND 兩種語句。在 ES 中使用 filter 方法添加過濾。代碼如下:

  /**   * 構建篩選條件   */  private void buildFilterQuery(BoolQueryBuilder boolQueryBuilder, Integer type, String category) {    // 內容類型篩選    if (type != null) {      BoolQueryBuilder typeFilterBuilder = QueryBuilders.boolQuery();      typeFilterBuilder.should(QueryBuilders.matchQuery(SearchConstant.TYPE_NAME, type).lenient(true));      boolQueryBuilder.filter(typeFilterBuilder);    }    // 內容類別篩選    if (!StringUtils.isEmpty(category)) {      BoolQueryBuilder categoryFilterBuilder = QueryBuilders.boolQuery();      categoryFilterBuilder.should(QueryBuilders.matchQuery(SearchConstant.CATEGORY_NAME, category).lenient(true));      boolQueryBuilder.filter(categoryFilterBuilder);    }  }

type 是大類,category 是小類,這樣就可以支持 大小類 篩選。但是如果需要在 type = 1 或者 type = 2 中搜索呢?具體實現代碼很簡單:

typeFilterBuilder  .should(QueryBuilders.matchQuery(SearchConstant.TYPE_NAME, 1)  .should(QueryBuilders.matchQuery(SearchConstant.TYPE_NAME, 2)  .lenient(true));

通過鏈式表達式,兩個 should 實現或,即 SQL 對應的 OR 語句。通過兩個 BoolQueryBuilder 實現與,即 SQL 對應的 AND 語句。

五、分頁、排序條件

分頁排序代碼就很簡單了:

 @Override  public PageBean searchContent(ContentSearchBean contentSearchBean) {    Integer pageNumber = contentSearchBean.getPageNumber();    Integer pageSize = contentSearchBean.getPageSize();    PageBean<ContentEntity> resultPageBean = new PageBean<>();    resultPageBean.setPageNumber(pageNumber);    resultPageBean.setPageSize(pageSize);    // 構建搜索短語    String searchContent = contentSearchBean.getSearchContent();    List<String> searchTermList = handlingSearchContent(searchContent);    // 構建查詢條件    BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();    buildMatchQuery(boolQueryBuilder, searchTermList);    // 構建篩選條件    buildFilterQuery(boolQueryBuilder, contentSearchBean.getType(), contentSearchBean.getCategory());    // 構建分頁、排序條件    Pageable pageable = PageRequest.of(pageNumber, pageSize);    if (!StringUtils.isEmpty(contentSearchBean.getOrderName())) {      pageable = PageRequest.of(pageNumber, pageSize, Sort.Direction.DESC, contentSearchBean.getOrderName());    }    SearchQuery searchQuery = new NativeSearchQueryBuilder().withPageable(pageable)        .withQuery(boolQueryBuilder).build();    // 搜索    LOGGER.info("/n ContentServiceImpl.searchContent() [" + searchContent        + "] /n DSL = /n " + searchQuery.getQuery().toString());    Page<ContentEntity> contentPage = contentRepository.search(searchQuery);    resultPageBean.setResult(contentPage.getContent());    resultPageBean.setTotalCount((int) contentPage.getTotalElements());    resultPageBean.setTotalPage((int) contentPage.getTotalElements() / resultPageBean.getPageSize() + 1);    return resultPageBean;  }

利用 Pageable 對象,構造分頁參數以及指定對應的 排序字段、排序順序(DESC ASC)即可。

六、小結

這個思路比較簡單。希望對大家的學習有所幫助,也希望大家多多支持VeVb武林網。


注:相關教程知識閱讀請移步到JAVA教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
日韩欧美999| 亚洲一区av在线播放| 亚洲区免费影片| 国产一区av在线| 国产中文字幕日韩| 亚洲精品视频免费| 一本色道久久综合狠狠躁篇的优点| 国产精品欧美激情在线播放| 亚洲大胆人体在线| 久久夜色精品国产欧美乱| 国产91精品久久久久| 欧美高清不卡在线| 国产精品亚洲精品| 国产亚洲精品综合一区91| 91精品国产91久久久久久不卡| 久久精品久久精品亚洲人| 日本在线观看天堂男亚洲| 国产日韩欧美自拍| 国产精品日韩在线播放| 爽爽爽爽爽爽爽成人免费观看| 精品免费在线视频| 国内精品一区二区三区四区| 欧美高清视频免费观看| 亚洲国产精品悠悠久久琪琪| 亚洲跨种族黑人xxx| 亚洲2020天天堂在线观看| 亚洲专区中文字幕| 欧美一级bbbbb性bbbb喷潮片| 精品视频在线播放色网色视频| 亚洲天堂免费观看| 欧美精品手机在线| 国产精品久久久久久久久久久不卡| 国产精品第一第二| 亚洲欧美中文字幕| 日韩免费看的电影电视剧大全| 久久6精品影院| 色婷婷久久一区二区| 久久视频国产精品免费视频在线| 一区二区三区视频观看| 日韩精品在线免费| 成人在线国产精品| 国产精品99久久久久久久久久久久| 日韩欧美高清在线视频| 日韩欧美国产免费播放| 日韩精品一区二区三区第95| 亚洲人成啪啪网站| 日韩av在线免费观看| 国产精品久久久久久久av电影| 欧美日韩国产成人高清视频| 精品国产拍在线观看| 97视频在线观看免费| 久久噜噜噜精品国产亚洲综合| 热99精品里视频精品| 91久久久久久久| 亚洲在线观看视频| 久久综合伊人77777尤物| 一区二区三区www| 日韩美女福利视频| 亚洲成人黄色在线| 国产成人黄色av| 日韩欧美成人区| 日韩在线资源网| 国产91久久婷婷一区二区| 国产精品丝袜白浆摸在线| 精品久久久香蕉免费精品视频| 久久精品国产欧美亚洲人人爽| 成人精品一区二区三区电影黑人| 久久福利网址导航| 亚洲三级黄色在线观看| 国产日韩精品电影| 久久久久久亚洲精品| 色综合伊人色综合网| 国产美女91呻吟求| 精品久久久久国产| 精品国产福利在线| 奇门遁甲1982国语版免费观看高清| 欧美成人全部免费| 97成人精品视频在线观看| 久久久久久久久网站| 中文字幕精品一区二区精品| 国产免费一区二区三区在线观看| 久久精品国产99国产精品澳门| 亚洲精品国产综合久久| 性日韩欧美在线视频| 日韩精品高清在线| 精品久久久久久久久中文字幕| 亚洲欧美在线播放| 久久久久久久爱| 久久亚洲国产精品成人av秋霞| 亚洲美女激情视频| 丝袜一区二区三区| 国产一区二区日韩精品欧美精品| 国产成人精品综合| 国产精品91久久| 日本免费久久高清视频| 久久免费视频网站| 欧美亚洲视频在线观看| 精品日本高清在线播放| 亚洲最大成人免费视频| 欧美放荡办公室videos4k| 欧美裸体xxxx极品少妇| 国产精品盗摄久久久| 亚洲精品黄网在线观看| 国产精选久久久久久| 欧美电影免费在线观看| 国产精品美乳一区二区免费| 国产97在线|亚洲| 欧美高清视频在线| 久久久久五月天| 久久久久久噜噜噜久久久精品| 色噜噜国产精品视频一区二区| 亚洲va电影大全| 成人激情电影一区二区| 久久久国产精品x99av| 日本成人激情视频| 成人xxxxx| 国产成人综合久久| 国产精品pans私拍| 国产日韩欧美成人| 欧美人成在线视频| 大胆欧美人体视频| 国产精品一区二区三区久久| 久久九九免费视频| 亚洲国产小视频在线观看| 欧美国产日韩一区二区三区| 国产精品嫩草影院久久久| 国产午夜一区二区| 欧美一级大片在线免费观看| 成人性生交大片免费看视频直播| 亚洲精品欧美日韩专区| 精品自在线视频| 国产伦精品一区二区三区精品视频| 亚洲激情电影中文字幕| 亚洲成色777777女色窝| 欧美精品中文字幕一区| 日韩高清电影免费观看完整版| 中文字幕亚洲无线码在线一区| 在线成人激情黄色| 91精品91久久久久久| www.久久撸.com| 精品国产91乱高清在线观看| 日韩美女主播视频| www.xxxx精品| 久久久久久久久亚洲| 亚洲另类欧美自拍| 成人做爰www免费看视频网站| 国产精品欧美日韩久久| 色多多国产成人永久免费网站| 日本一本a高清免费不卡| 亚洲3p在线观看| 日日骚av一区| 国产精品一区二区三区在线播放| 色哟哟入口国产精品| 日韩hd视频在线观看| 久久久久国产一区二区三区| 欧美精品在线观看| 欧美日韩在线视频首页| 久久精品精品电影网| 在线日韩第一页| 亚洲精品有码在线| 日韩欧美国产成人| 91在线视频一区| 欧美巨乳在线观看| 国产精品永久免费|