Spring Boot + Elasticsearch實現大批量數據集下中文的精確匹配

緣由

數據存儲在MYSQ庫中,數據基本維持不變,但數據量又較大(幾千萬)放在MYSQL中查詢效率上較慢,尋求一種簡單有效的方式提高查詢效率,MYSQL並不擅長大規模數據量下的數據查詢。

技術方案

考慮後期同樣會使用到es,此次直接結合spring-boot框架形成一個獨立服務,並不涉及UI展現內容,(ES版本2.4.5,5.0+版本的話就不能再使用spring data elasticsearch)技術組合如下:

Spring Boot+ Spring-data-elasticsearch + Elasticsearch

結合elasticsearch-jdbc插件,全量將數據一次性導入es中,後期不涉及數據變更。

es安裝

測試期間單機安裝,官網下載對應版本,由於筆者工作環境基於JDK7,所以下載5.0以下版本,5.0+均依賴Java8,同時使用到elasticsearch-jdbc插件,一併下載安裝完成。

走過的大彎路

直接使用elasticsearch-jdbc工具,編寫腳本文件,抽取數據到es中,腳本樣例如下:

#!/bin/shDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"bin=${DIR}/../binlib=${DIR}/../libecho '{ "type": "jdbc", "jdbc": { "elasticsearch.autodiscover": true, "url": "jdbc:mysql://192.168.1.3:3306/test", "user": "root", "password": "root", "sql": "SELECT * from tb_name1", "elasticsearch": { "host": "192.168.1.1", "port": 9300 }, "index": "my-index", "type": "my-type" }}' | java \ -cp "${lib}/*" \ -Dlog4j.configurationFile=${bin}/log4j2.xml \ org.xbib.tools.Runner \ org.xbib.tools.JDBCImporter

數據導入成功後,可使用head插件直接查看到。使用基本查詢測試,查詢條件是name=測試&num=100,使用精確匹配term語句,查詢數據未果,實際使用num=100獨立查詢時,有相關數據。

問題跟蹤解決

導致此現象的原因在於中文分詞的問題,使用elasticsearch-jdbc腳本中並未處理列的mapping類型。(中間做過一次嘗試,在腳本中定義對應的type_mapping,但並未成功,有興趣的朋友可再做嘗試)。

注:es與ik分詞插件結合,版本匹配需要特別關注,但本案例並不涉及

結合此案例,查詢時並不需要分詞,而是精確匹配,但es默認情況下是指定string類型的分詞,所以在index創建之前我們需要手動指定相關列不需要分詞:not_analyzed,形如:

CURL -XPOST //192.168.1.105:9200/my-index -d { { "mappings": { "my-type": { "properties": { "name": { "type": "string", "index": "not_analyzed" }, "num": { "type": "string", "index": "not_analyzed" } } } }}

創建索引成功後,再使用elasticsearch-jdbc的腳本導入數據,相關數據列不會再使用分詞分析,再使用term組合精確查詢時,就可以查詢相關數據來。

SpringBoot應用

pom.xml關鍵配置

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-elasticsearch</artifactId></dependency><dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <exclusions> <exclusion> <artifactId>log4j-over-slf4j</artifactId> <groupId>org.slf4j</groupId> </exclusion> </exclusions></dependency><dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId> </exclusion> </exclusions></dependency><dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope></dependency><dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-log4j</artifactId> <version>1.3.1.RELEASE</version></dependency>

與elasticsearch交互實體

@Data@Document(indexName = "my-index", type = "my-type", shards = 5, replicas = 1, indexStoreType = "fs", refreshInterval = "-1")public class DataBean { /** * code:名稱 * * @since JDK 1.6 */ public String name; /** * msg:編號 * * @since JDK 1.6 */ public String num;}

與es交互接口類,返回數據的唯一_id值,若查得數據表示命中數據,若為空並未數據不存在

public interface DataBeanRepository extends ElasticsearchRepository<DataBean, Long> { //案例中並未使用,但可以用 public List<BlackGreyData> findByNameAndNum(String name, String num);}

下面是業務處理層,採用BoolQueryBuilder構建查詢條件,也即可基於DSL模塊查詢數據,還可以採用Criteria查詢。

@Autowired DataBeanRepository repository; @Override public List<DataBean> query(String name, String num, String type) { //採用過濾器的形式,提高查詢效率 BoolQueryBuilder builder = QueryBuilders.boolQuery(); builder.must(QueryBuilders.termQuery("name", name)).must(QueryBuilders.termQuery("num", num)); Iterable<DataBean> lists = repository.search(builder); List<DataBean> datas = new ArrayList<>(); for (DataBean dataBean : lists) { datas.add(dataBean); logger.info("---------------------->>>Request result = 【" + dataBean + "】"); } return datas; }

其它再編寫對應的請求響應邏輯,即可完成簡單服務的完成。

測試結果

GPS數據量5000W+,精確匹配查詢出來50條數據,耗時700ms左右,結果查詢緩存機制,基本可以穩定在300ms左右。這也是在單節點,未作任何優化的情況的結果。

源碼地址

https://github.com/backkoms/spring-boot-elasticsearch

Spring Boot + Elasticsearch實現大批量數據集下中文的精確匹配

擴展閱讀:

  • Spring Boot + Elasticsearch 實現索引的日常維護

  • Spring Boot + Elasticsearch 實現索引批量寫入

  • Nginx+Lua+MySQL/Redis實現高性能動態網頁展現

  • Nginx+Lua+Redis實現高性能緩存數據讀取

  • 基於SpringCloud的Microservices架構實戰案例-序篇

  • 介紹幾款常用的在線API管理工具

  • 野蠻生長的前端,從雜牌軍到正規軍

相關推薦

推薦中...