[Springboot實戰系列]整合ElasticSearch實現數據模糊搜索(Logstash同步Mysql數據)

在這裏插入圖片描述

前言

本文介紹瞭如何整合搜索引擎elasticsearch與springboot,對外提供數據查詢接口。前端

業務介紹

個人我的網站須要對mysql數據庫內存儲的京東商品進行模糊查詢(模仿淘寶商品搜索),因此選擇了將數據導入elasticsearch隨後使用他來進行關鍵詞查詢。前端只需發送用戶搜索的關鍵詞和分頁參數(可選),便可返回商品數據(json格式)java

開發環境

組件介紹:node

  • elasticsearch:搜索引擎,用於存儲待搜索數據
  • logstash:用於將mysql中的商品數據同步到搜索引擎中
  • elasticsearch-head(可選):elasticsearch可視化工具
  • kibana(可選):elasticsearch可視化工具

本文測試環境:mysql

  • springboot:1.5.16
  • elasticsearch:2.3.5(springboot1.5僅支持2.x的es)
  • logstash:6.5.4

開發步驟

使用Docker部署elasticsearch

  • docker下一鍵啓動es,可根據須要的版本號對語句作修改
sudo docker run -it --rm --name elasticsearch -d -p 9200:9200 -p 9300:9300 elasticsearch:2.3.5
複製代碼

注意到該命令:git

  • --rm參數:容器終止後銷燬
  • -d:後臺進程
  • -p 9200:9200 -p 9300:9300:開放了9200端口和9300端口

獲得如圖:github

在這裏插入圖片描述

此時打開網頁localhost:9200便可查看狀態,顯示相似爲:算法

{
  "name" : "Ant-Man",
  "cluster_name" : "elasticsearch",
  "version" : {
    "number" : "2.3.5",
    "build_hash" : "90f439ff60a3c0f497f91663701e64ccd01edbb4",
    "build_timestamp" : "2016-07-27T10:36:52Z",
    "build_snapshot" : false,
    "lucene_version" : "5.5.0"
  },
  "tagline" : "You Know, for Search"
}
複製代碼

注意:docker的es默認對0.0.0.0公網開放spring

下載並使用logstash並導入數據

本文中要導入的是pm_backend下的表pm_jd_item內的所有京東商品數據sql

詳細步驟參考:docker

blog.codecp.org/2018/04/16/…

最終編寫的jdbc.conf爲:

schedule => "* * * * *"默認爲每分鐘同步一次

input {
  jdbc {
    jdbc_connection_string => "jdbc:mysql://localhost:3306/pm_backend"
    jdbc_user => "root"
    jdbc_password => "xxxxxxxxxx"
    jdbc_driver_library => "xxxxxxxx/mysql-connector-java-5.1.6.jar"
    jdbc_driver_class => "com.mysql.jdbc.Driver"
    jdbc_paging_enabled => "true"
    jdbc_page_size => "5000"
    statement=> "select * from pm_jd_item"
    schedule => "* * * * *"
    type => "pm_jd_item"
  }
}

output {
  elasticsearch {
    hosts => "localhost:9200"
    index => "pm_backend"
    document_type => "%{type}"
    document_id => "%{id}"
  }
  stdout {
    codec => json_lines
  }
}
複製代碼

在logstash目錄下執行命令,完成數據的導入:

bin/logstash -f jdbc.conf
複製代碼

獲得如圖:

在這裏插入圖片描述

同步完成後,使用elasticsearch-head查看(或者用kibana,請隨意):

在這裏插入圖片描述

整合進springboot

  1. 添加pom.xml
<!-- 搜索引擎:elastic-search-->
<dependency>
	<groupId>org.elasticsearch</groupId>
	<artifactId>elasticsearch</artifactId>
	 <version>2.4.6</version>
</dependency>
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
<dependency>
	<groupId>org.springframework.data</groupId>
	<artifactId>spring-data-elasticsearch</artifactId>
</dependency>
複製代碼
  1. 修改application.properties
# elasticsearch
spring.data.elasticsearch.cluster-name=elasticsearch
#節點地址,多個節點用逗號隔開
spring.data.elasticsearch.cluster-nodes=127.0.0.1:9300
#spring.data.elasticsearch.local=false
spring.data.elasticsearch.repositories.enable=true
複製代碼
  1. 在須要進行搜索的實體類上添加@Document、@Id、@Field等標註,本例爲JdItem.java
@Document(indexName = "pm_backend", type = "pm_jd_item")
public class JdItem implements Serializable {

    @Id
    private Integer id;

    @Field(type = FieldType.Long)
    private Long itemId;

    @Field(type = FieldType.Long)
    private Long categoryId;

    @Field(type = FieldType.String)
    private String name;
複製代碼
  1. 添加JdItemRepository繼承ElasticsearchRepository
public interface JdItemRepository extends ElasticsearchRepository<JdItem, Integer>{
}

複製代碼
  1. 編寫JdItemController中的查詢接口findJdItemByName

代碼截取自我的項目京東價格監控,僅供參考!

/** * 根據商品名在pm_jd_item中搜索商品 * @param itemName * @param startRow * @param pageSize * @return */
    @ApiOperation(value="查詢商品", notes="查詢商品")
    @RequestMapping(value = "/findJdItemByName", method = {RequestMethod.GET})
    public ResponseData<List<JdItem>> findJdItemByName(
            @ApiParam("用戶輸入的商品名") @RequestParam(value = "itemName") String itemName,
            @ApiParam("頁碼索引(默認爲0)") @RequestParam(value = "startRow", required = false, defaultValue = "0") int startRow,
            @ApiParam("每頁的商品數量(默認爲10)") @RequestParam(value = "pageSize", required = false, defaultValue = "10") int pageSize
    ){
        ResponseData<List<JdItem>> responseData = new ResponseData<>();
        try {

            FunctionScoreQueryBuilder functionScoreQueryBuilder = QueryBuilders.functionScoreQuery().add(QueryBuilders.matchPhraseQuery("name", itemName), ScoreFunctionBuilders.weightFactorFunction(100)).scoreMode("sum").setMinScore(10);
            Pageable pageable = new PageRequest(startRow, pageSize);
            SearchQuery searchQuery = new NativeSearchQueryBuilder().withPageable(pageable).withQuery(functionScoreQueryBuilder).build();
            Page<JdItem> jdItems = jdItemRepository.search(searchQuery);
            // Page分頁getTotalPages()返回了應有的頁數,臨時放在errorMsg傳給前端
            responseData.jsonFill(1, String.valueOf(jdItems.getTotalPages()), jdItems.getContent());
        } catch (Exception e) {
            e.printStackTrace();
            responseData.jsonFill(2, e.getMessage(), null);
        }
        return responseData;
    }
}
複製代碼
  1. 運行springboot

調用findJdItemByName接口,獲得:

在這裏插入圖片描述

整合分詞器功能

請參考:github.com/medcl/elast…

參考

Docker安裝ES & Kibana:

www.jianshu.com/p/fdfead5ac…

Elasticsearch之使用Logstash導入Mysql數據:

blog.codecp.org/2018/04/16/…

關注我

我是蠻三刀把刀,後端開發。主要關注後端開發,數據安全,爬蟲等方向。

來微信和我聊聊:yangzd1102

Github我的主頁:

github.com/qqxx6661

原創博客主要內容

  • Java知識點複習全手冊
  • Leetcode算法題解析
  • 劍指offer算法題解析
  • Python爬蟲相關技術實戰
  • 後端開發相關技術實戰
  • SpringCloud實戰

我的公衆號:Rude3Knife

若是文章對你有幫助,不妨收藏起來並轉發給您的朋友們~

相關文章
相關標籤/搜索