中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

SpringBoot整合ElasticSearch實現多版本的兼容

發布時間:2020-06-14 13:32:31 來源:網絡 閱讀:1966 作者:沙漏半杯 欄目:編程語言

前言

本篇主要是介紹和使用目前最火的搜索引擎ElastiSearch,并和SpringBoot進行結合使用。

ElasticSearch介紹

ElasticSearch是一個基于Lucene的搜索服務器,其實就是對Lucene進行封裝,提供了 REST API 的操作接口?ElasticSearch作為一個高度可拓展的開源全文搜索和分析引擎,可用于快速地對大數據進行存儲,搜索和分析。
ElasticSearch主要特點:分布式、高可用、異步寫入、多API、面向文檔 。
ElasticSearch核心概念:近實時,集群,節點(保存數據),索引,分片(將索引分片),副本(分片可設置多個副本) 。它可以快速地儲存、搜索和分析海量數據。
ElasticSearch使用案例:維基百科、Stack Overflow、Github 等等。

SpringBoot整合Elasticsearch

在使用SpringBoot整合Elasticsearch?之前,我們應該了解下它們之間對應版本的關系。

Spring Boot Version (x)Spring Data Elasticsearch Version (y)Elasticsearch Version (z)
x <= 1.3.5y <= 1.3.4z <= 1.7.2*
x >= 1.4.x2.0.0 <=y < 5.0.0**2.0.0 <= z < 5.0.0**

這里我們使用的SpringBoot的版本是1.5.9,Elasticsearch的版本是2.3.5。

使用SpringBoot整合Elasticsearch,一般都是使用?SpringData?進行封裝的,然后再dao層接口繼承ElasticsearchRepository?類,該類實現了很多的方法,比如常用的CRUD方法。

SpringData的使用

首先,在使用之前,先做好相關的準備。

Maven的配置如下:
<dependency>
????????????<groupId>org.springframework.boot</groupId>
????????????<artifactId>spring-boot-starter-web</artifactId>
?????????????<version>1.5.9.RELEASE</version>
????????</dependency>
??<dependency>
????????????<groupId>org.springframework.boot</groupId>
????????????<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
?????????????<version>1.5.9.RELEASE</version>
????????</dependency>
application.properties的配置
spring.data.elasticsearch.repositories.enabled?=?truespring.data.elasticsearch.cluster-nodes?=127.0.0.1\:9300

注: 9300 是 Java 客戶端的端口。9200 是支持 Restful HTTP 的接口。

更多的配置:

spring.data.elasticsearch.cluster-name?Elasticsearch?集群名。(默認值:?elasticsearch)spring.data.elasticsearch.cluster-nodes?集群節點地址列表,用逗號分隔。如果沒有指定,就啟動一個客戶端節點。spring.data.elasticsearch.propertie?用來配置客戶端的額外屬性。spring.data.elasticsearch.repositories.enabled?開啟?Elasticsearch?倉庫。(默認值:true。)
代碼編寫

實體類

@Document(indexName?=?"userindex",?type?=?"user")
public?class?User?implements?Serializable{?????/**?????*??????*/
????private?static?final?long?serialVersionUID?=?1L;????/**?編號?*/
?????private?Long?id;?????/**?姓名?*/
?????private?String?name;?????
?????/**?年齡?*/
?????private?Integer?age;?????
?????/**?描述?*/??
?????private?String?description;?????
?????/**?創建時間?*/
?????private?String?createtm;????//?getter和setter?略}

使用SpringData的時候,它需要在實體類中設置indexName?和type?,如果和傳統型數據庫比較的話,就相當于。需要注意的是indexNametype都必須是小寫!!!

dao層

public?interface?UserDao?extends?ElasticsearchRepository<User,?Long>{}

dao層這里就比較簡單了,只需繼承ElasticsearchRepository該類就行了。其中主要的方法就是 save、delete和search。其中save方法相當如insert和update,沒有就新增,有就覆蓋。delete方法主要就是刪除數據以及索引庫。至于search就是查詢了,包括一些常用的查詢,如分頁、權重之類的。

Service層

@Servicepublic?class?UserServiceImpl?implements?UserService?{????@Autowired
????private?UserDao?userDao;????@Override
????public?boolean?insert(User?user)?{????????boolean?falg=false;????????try{
????????????userDao.save(user);
????????????falg=true;
????????}catch(Exception?e){
????????????e.printStackTrace();
????????}????????return?falg;
????}????@Override
????public?List<User>?search(String?searchContent)?{
??????????QueryStringQueryBuilder?builder?=?new?QueryStringQueryBuilder(searchContent);
??????????System.out.println("查詢的語句:"+builder);
??????????Iterable<User>?searchResult?=?userDao.search(builder);
??????????Iterator<User>?iterator?=?searchResult.iterator();
??????????List<User>?list=new?ArrayList<User>();??????????while?(iterator.hasNext())?{
????????????list.add(iterator.next());
??????????}???????return?list;
????}????
????
????
????@Override
????public?List<User>?searchUser(Integer?pageNumber,?Integer?pageSize,String?searchContent)?{?????????//?分頁參數
????????Pageable?pageable?=?new?PageRequest(pageNumber,?pageSize);
????????QueryStringQueryBuilder?builder?=?new?QueryStringQueryBuilder(searchContent);
????????SearchQuery?searchQuery?=?new?NativeSearchQueryBuilder().withPageable(pageable).withQuery(builder).build();
????????System.out.println("查詢的語句:"?+?searchQuery.getQuery().toString());
????????Page<User>?searchPageResults?=?userDao.search(searchQuery);????????return?searchPageResults.getContent();
????}????

????@Override
????public?List<User>?searchUserByWeight(String?searchContent)?{?????//?根據權重進行查詢
????????FunctionScoreQueryBuilder?functionScoreQueryBuilder?=?QueryBuilders.functionScoreQuery()
????????????????.add(QueryBuilders.boolQuery().should(QueryBuilders.matchQuery("name",?searchContent)),
????????????????????ScoreFunctionBuilders.weightFactorFunction(10))
????????????????.add(QueryBuilders.boolQuery().should(QueryBuilders.matchQuery("description",?searchContent)),
????????????????????????ScoreFunctionBuilders.weightFactorFunction(100)).setMinScore(2);
????????System.out.println("查詢的語句:"?+?functionScoreQueryBuilder.toString());
????????Iterable<User>?searchResult?=?userDao.search(functionScoreQueryBuilder);
????????Iterator<User>?iterator?=?searchResult.iterator();
????????List<User>?list=new?ArrayList<User>();????????while?(iterator.hasNext())?{
????????????list.add(iterator.next());
????????}????????return?list;
????}
}

這里我就簡單的寫了幾個方法,其中主要的方法是查詢。查詢包括全文搜索,分頁查詢和權重查詢。其中需要說明的是權重查詢這塊,權重的分值越高,查詢的結果也越靠前,如果沒有對其它的數據設置分值,它們默認的分值就是1,如果不想查詢這些語句,只需使用setMinScore將其設為大于1即可。

代碼測試

調用接口進行添加數據

新增數據:

POST?http://localhost:8086/api/user{"id":1,"name":"張三","age":20,"description":"張三是個Java開發工程師","createtm":"2018-4-25?11:07:42"}
{"id":2,"name":"李四","age":24,"description":"李四是個測試工程師","createtm":"1980-2-15?19:01:32"}
{"id":3,"name":"王五","age":25,"description":"王五是個運維工程師","createtm":"2016-8-21?06:11:32"}

進行全文查詢
請求

http://localhost:8086/api/user?searchContent=工程師

返回

[{"id":2,"name":"李四","age":14,"description":"李四是個測試工程師","createtm":?"1980-2-15?19:01:32"},
{"id":1,"name":"張三","age":20,"description":"張三是個Java開發工程師",?"createtm":?"2018-4-25?11:07:42"},
{"id":3,"name":"王五","age":25,"description":"王五是個運維工程師","createtm":?"2016-8-21?06:11:32"}]

進行分頁查詢
請求

http://localhost:8086/api/user?pageNumber=0&pageSize=2&searchContent=工程師

返回

[{"id":2,"name":"李四","age":14,"description":"李四是個測試工程師"},{"id":1,"name":"張三","age":20,"description":"張三是個Java開發工程師"}]

進行權重查詢
請求

http://localhost:8086/api/user2?searchContent=李四

返回

[{"id":2,"name":"李四","age":24,"description":"李四是個測試工程師","createtm":"1980-2-15?19:01:32"}]

權重查詢打印的語句:

查詢的語句:{{??"function_score"?:?{????"functions"?:?[?{??????"filter"?:?{????????"bool"?:?{??????????"should"?:?{????????????"match"?:?{??????????????"name"?:?{????????????????"query"?:?"李四",????????????????"type"?:?"boolean"
??????????????}
????????????}
??????????}
????????}
??????},??????"weight"?:?10.0
????},?{??????"filter"?:?{????????"bool"?:?{??????????"should"?:?{????????????"match"?:?{??????????????"description"?:?{????????????????"query"?:?"李四",????????????????"type"?:?"boolean"
??????????????}
????????????}
??????????}
????????}
??????},??????"weight"?:?100.0
????}?],????"min_score"?:?2.0
??}
}

注:測試中,因為設置了setMinScore最小權重分為2的,所以無關的數據是不會顯示出來的。如果想顯示的話,在代碼中去掉即可。

新增完數據之后,可以在瀏覽器輸入:http://localhost:9200/_plugin/head/
然后點擊基本查詢,便可以查看添加的數據。如果想用語句查詢,可以將程序中控制臺打印的查詢語句粘貼到查詢界面上進行查詢!
SpringBoot整合ElasticSearch實現多版本的兼容

注:這里的ElasticSearch是我在windows上安裝的,并安裝了ES插件head,具體安裝步驟在文章末尾。

除了SpringData之外,其實還有其它的方法操作ElasticSearch的。
比如使用原生ElasticSearch的Api,使用TransportClient類實現。
或者使用由Spring封裝,只需在Service層,進行注入Bean即可。
示例:

@Autowired
?ElasticsearchTemplate?elasticsearchTemplate;

但是,上述方法中都有其局限性,也就是隨著ElasticSearch的版本變更,相關的Java API也在做不斷的調整,就是ElasticSearch服務端版本進行更改之后,客戶端的代碼可能需要重新編寫。
因此介紹一個相當好用的第三方工具JestClient,它對ElasticSearch進行封裝,填補了?ElasticSearch?HttpRest接口 客戶端的空白,它適用于ElasticSearch2.x以上的版本,無需因為ElasticSearch服務端版本更改而對代碼進行更改!

JestClient

首先在Maven中添加如下依賴:

????<dependency>
????????<groupId>io.searchbox</groupId>?
?????????<artifactId>jest</artifactId>
????????<version>5.3.3</version>
????</dependency>

然后編寫相關的測試代碼。
代碼中的注釋應該很完整,所以這里就不再對代碼過多的講述了。

import?java.util.ArrayList;import?java.util.List;import?org.elasticsearch.index.query.QueryBuilders;import?org.elasticsearch.search.builder.SearchSourceBuilder;import?com.pancm.pojo.User;import?io.searchbox.client.JestClient;import?io.searchbox.client.JestClientFactory;import?io.searchbox.client.JestResult;import?io.searchbox.client.config.HttpClientConfig;import?io.searchbox.core.Bulk;import?io.searchbox.core.BulkResult;import?io.searchbox.core.Delete;import?io.searchbox.core.DocumentResult;import?io.searchbox.core.Index;import?io.searchbox.core.Search;import?io.searchbox.indices.CreateIndex;import?io.searchbox.indices.DeleteIndex;import?io.searchbox.indices.mapping.GetMapping;import?io.searchbox.indices.mapping.PutMapping;public?class?JestTest?{??
????????private?static?JestClient?jestClient;??
????????private?static?String?indexName?=?"userindex";??
//??????private?static?String?indexName?=?"userindex2";??
????????private?static?String?typeName?=?"user";??
????????private?static?String?elasticIps="http://192.169.2.98:9200";//??????private?static?String?elasticIps="http://127.0.0.1:9200";
????????
????????
????????public?static?void?main(String[]?args)?throws?Exception?{
????????????jestClient?=?getJestClient();??
????????????insertBatch();
????????????serach2();
????????????serach3();
????????????serach4();
????????????jestClient.close();??
????????????
????????}????????
????????private?static??JestClient?getJestClient()?{??
????????????JestClientFactory?factory?=?new?JestClientFactory();??
????????????factory.setHttpClientConfig(new?HttpClientConfig.Builder(elasticIps).connTimeout(60000).readTimeout(60000).multiThreaded(true).build());??
????????????return?factory.getObject();??
????????}??
????????
????????public?static?void?insertBatch()?{
????????????List<Object>?objs?=?new?ArrayList<Object>();
????????????objs.add(new?User(1L,?"張三",?20,?"張三是個Java開發工程師","2018-4-25?11:07:42"));
????????????objs.add(new?User(2L,?"李四",?24,?"李四是個測試工程師","1980-2-15?19:01:32"));
????????????objs.add(new?User(3L,?"王五",?25,?"王五是個運維工程師","2016-8-21?06:11:32"));????????????boolean?result?=?false;????????????try?{
????????????????result?=?insertBatch(jestClient,indexName,?typeName,objs);
????????????}?catch?(Exception?e)?{
????????????????e.printStackTrace();
????????????}
????????????System.out.println("批量新增:"+result);
????????}????????
????????
????????/**
?????????*?全文搜索
?????????*/
????????public?static?void?serach2()?{
????????????String?query?="工程師";????????????try?{
????????????????SearchSourceBuilder?searchSourceBuilder?=?new?SearchSourceBuilder();?
?????????????????searchSourceBuilder.query(QueryBuilders.queryStringQuery(query));?
?????????????????//分頁設置
?????????????????searchSourceBuilder.from(0).size(2);?
????????????????System.out.println("全文搜索查詢語句:"+searchSourceBuilder.toString());
????????????????System.out.println("全文搜索返回結果:"+search(jestClient,indexName,?typeName,?searchSourceBuilder.toString()));
????????????}?catch?(Exception?e)?{
????????????????e.printStackTrace();
????????????}
????????}????????
????????/**
?????????*?精確搜索
?????????*/
????????public?static?void?serach3()?{????????????try?{
????????????????SearchSourceBuilder?searchSourceBuilder?=?new?SearchSourceBuilder();?
????????????????searchSourceBuilder.query(QueryBuilders.termQuery("age",?24));?
????????????????System.out.println("精確搜索查詢語句:"+searchSourceBuilder.toString());
????????????????System.out.println("精確搜索返回結果:"+search(jestClient,indexName,?typeName,?searchSourceBuilder.toString()));
????????????}?catch?(Exception?e)?{
????????????????e.printStackTrace();
????????????}
????????}????????
????????
????????/**
?????????*?區間搜索
?????????*/
????????public?static?void?serach4()?{
????????????String?createtm="createtm";
????????????String?from="2016-8-21?06:11:32";
????????????String?to="2018-8-21?06:11:32";????????????
????????????try?{
????????????????SearchSourceBuilder?searchSourceBuilder?=?new?SearchSourceBuilder();?
????????????????searchSourceBuilder.query(QueryBuilders.rangeQuery(createtm).gte(from).lte(to));?
????????????????System.out.println("區間搜索語句:"+searchSourceBuilder.toString());
????????????????System.out.println("區間搜索返回結果:"+search(jestClient,indexName,?typeName,?searchSourceBuilder.toString()));
????????????}?catch?(Exception?e)?{
????????????????e.printStackTrace();
????????????}
????????}????????
????????
????????/**
?????????*?創建索引
?????????*?@param?indexName
?????????*?@return
?????????*?@throws?Exception
?????????*/
????????public?boolean?createIndex(JestClient?jestClient,String?indexName)?throws?Exception?{??
????????????JestResult?jr?=?jestClient.execute(new?CreateIndex.Builder(indexName).build());??
????????????return?jr.isSucceeded();??
????????}??
??????????
????????/**
?????????*?新增數據
?????????*?@param?indexName
?????????*?@param?typeName
?????????*?@param?source
?????????*?@return
?????????*?@throws?Exception
?????????*/
????????public?boolean?insert(JestClient?jestClient,String?indexName,?String?typeName,?String?source)?throws?Exception?{??
????????????PutMapping?putMapping?=?new?PutMapping.Builder(indexName,?typeName,?source).build();??
????????????JestResult?jr?=?jestClient.execute(putMapping);??
????????????return?jr.isSucceeded();??
????????}??
??????????
????????
?????????/**
??????????*?查詢數據
??????????*?@param?indexName
??????????*?@param?typeName
??????????*?@return
??????????*?@throws?Exception
??????????*/
????????public?static?String?getIndexMapping(JestClient?jestClient,String?indexName,?String?typeName)?throws?Exception?{??
????????????GetMapping?getMapping?=?new?GetMapping.Builder().addIndex(indexName).addType(typeName).build();??
????????????JestResult?jr?=jestClient.execute(getMapping);??
????????????return?jr.getJsonString();??
?????????}??
??????????
????????
????????
???????/**
????????*?批量新增數據
????????*?@param?indexName
????????*?@param?typeName
????????*?@param?objs
????????*?@return
????????*?@throws?Exception
????????*/
????????public?static?boolean?insertBatch(JestClient?jestClient,String?indexName,?String?typeName,?List<Object>?objs)?throws?Exception?{??
????????????Bulk.Builder?bulk?=?new?Bulk.Builder().defaultIndex(indexName).defaultType(typeName);??
????????????for?(Object?obj?:?objs)?{??
????????????????Index?index?=?new?Index.Builder(obj).build();??
?????????????????bulk.addAction(index);??
????????????}??
????????????BulkResult?br?=?jestClient.execute(bulk.build());??
????????????return?br.isSucceeded();??
???????????}??
??????????
????????/**
?????????*?全文搜索
?????????*?@param?indexName
?????????*?@param?typeName
?????????*?@param?query
?????????*?@return
?????????*?@throws?Exception
?????????*/
????????public?static?String?search(JestClient?jestClient,String?indexName,?String?typeName,?String?query)?throws?Exception?{??
?????????????Search?search?=?new?Search.Builder(query)
?????????????.addIndex(indexName)
?????????????.addType(typeName)??
?????????????.build();?
????????????JestResult?jr?=?jestClient.execute(search);??
//??????????System.out.println("--"+jr.getJsonString());//??????????System.out.println("--"+jr.getSourceAsObject(User.class));
????????????return?jr.getSourceAsString();??
?????????}??
??????????
??????????
????????
???????
??????????
???????/**
????????*?刪除索引
????????*?@param?indexName
????????*?@return
????????*?@throws?Exception
????????*/
????????public?boolean?delete(JestClient?jestClient,String?indexName)?throws?Exception?{??
????????????JestResult?jr?=?jestClient.execute(new?DeleteIndex.Builder(indexName).build());??
????????????return?jr.isSucceeded();??
????????}??
??????????
???????/**
????????*?刪除數據
????????*?@param?indexName
????????*?@param?typeName
????????*?@param?id
????????*?@return
????????*?@throws?Exception
????????*/
????????public?boolean?delete(JestClient?jestClient,String?indexName,?String?typeName,?String?id)?throws?Exception?{??
????????????DocumentResult?dr?=?jestClient.execute(new?Delete.Builder(id).index(indexName).type(typeName).build());??
????????????return?dr.isSucceeded();??
????????}

注:測試之前先說明下,本地windows系統安裝的是ElasticSearch版本是2.3.5,linux服務器上安裝的ElasticSearch版本是6.2。

測試結果

全文搜索

全文搜索查詢語句:{??"from"?:?0,??"size"?:?2,??"query"?:?{????"query_string"?:?{??????"query"?:?"工程師"
????}
??}
}

全文搜索返回結果:{"id":1,"name":"張三","age":20,"description":"張三是個Java開發工程師","createtm":"2018-4-25?11:07:42"},{"id":2,"name":"李四","age":24,"description":"李四是個測試工程師","createtm":"1980-2-15?19:01:32"}

匹配搜索

精確搜索查詢語句:{??"query"?:?{????"term"?:?{??????"age"?:?24
????}
??}
}

精確搜索返回結果:{"id":2,"name":"李四","age":24,"description":"李四是個測試工程師","createtm":"1980-2-15?19:01:32"}

時間區間搜索

區間搜索語句:{??"query"?:?{????"range"?:?{??????"createtm"?:?{????????"from"?:?"2016-8-21?06:11:32",????????"to"?:?"2018-8-21?06:11:32",????????"include_lower"?:?true,????????"include_upper"?:?true
??????}
????}
??}
}
區間搜索返回結果:{"id":1,"name":"張三","age":20,"description":"張三是個Java開發工程師","createtm":"2018-4-25?11:07:42"}

新增完數據之后,我們可以上linux的?Kibana中進行相關的查詢,查詢結果如下:

SpringBoot整合ElasticSearch實現多版本的兼容

注:Kibana 是屬于ELK中一個開源軟件。Kibana可以為 Logstash 和 ElasticSearch 提供的日志分析友好的 Web 界面,可以幫助匯總、分析和搜索重要數據日志。

上述代碼中測試返回的結果符合我們的預期。其中關于JestClient只是用到了很少的一部分,更多的使用可以查看JestClient的官方文檔。

Windows安裝ElasticSearch

1,文件準備
下載地址:
https://www.elastic.co/downloads
選擇ElasticSearch相關版本, 然后選擇后綴名為ZIP文件進行下載,下載之后進行解壓。

2,啟動Elasticsearch
進入bin目錄下,運行 elasticsearch.bat
然后在瀏覽上輸入: localhost:9200
成功顯示一下界面表示成功!
SpringBoot整合ElasticSearch實現多版本的兼容

3,安裝ES插件
web管理界面head 安裝
進入bin目錄下,打開cmd,進入dos界面
輸入:plugin install mobz/elasticsearch-head
進行下載
成功下載之后,在瀏覽器輸入:http://localhost:9200/_plugin/head/
若顯示一下界面,則安裝成功!
SpringBoot整合ElasticSearch實現多版本的兼容

4,注冊服務
進入bin目錄下,打開cmd,進入dos界面
依次輸入:
service.bat install
service.bat start
成功之后,再輸入
services.msc
跳轉到Service服務界面,可以直接查看es的運行狀態!

歡迎工作一到五年的Java工程師朋友們加入Java技術交流:659270626
群內提供免費的Java架構學習資料(里面有高可用、高并發、高性能及分布式、Jvm性能調優、Spring源碼,MyBatis,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多個知識點的架構資料)合理利用自己每一分每一秒的時間來學習提升自己,不要再用"沒有時間“來掩飾自己思想上的懶惰!趁年輕,使勁拼,給未來的自己一個交代!


向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

富阳市| 常德市| 石渠县| 望奎县| 承德市| 名山县| 荔波县| 德安县| 绍兴县| 松桃| 开封县| 固安县| 平舆县| 甘谷县| 瓦房店市| 柳江县| 甘德县| 徐水县| 漳州市| 龙岩市| 余干县| 肥城市| 密山市| 微山县| 闸北区| 偏关县| 林西县| 西青区| 曲靖市| 禹州市| 运城市| 贡嘎县| 蒙城县| 南皮县| 余庆县| 靖江市| 两当县| 清丰县| 修文县| 托克托县| 临猗县|