Spring?Data?Elasticsearch使用方式(Elasticsearch)
1. 項(xiàng)目部署
1.1 添加依賴(lài)
在項(xiàng)目的 pom.xml 中引?Spring Data Elasticsearch的啟動(dòng)器。
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-elasticsearch</artifactId> </dependency>
1.2 配置application.yml 文件
spring: data: elasticsearch: cluster-name: csdn-elastic cluster-nodes: 127.0.0.1:9301,127.0.0.1:9302,127.0.0.1:9303
需要注意的是,Spring Data Elasticsearch底層使?的不是Elasticsearch提供的RestHighLevelClient,?是 TransportClient,并不采?HTTP協(xié)議通信,?是訪問(wèn)Elasticsearch對(duì)外開(kāi)放的TCP端?。
我們?cè)谥凹号渲?中,設(shè)置的端?分別是:9301、9302、9303。
1.3 測(cè)試是否注入成功
在test測(cè)試?件夾下的com.csdn.es包下創(chuàng)建?個(gè)SpringDataESTests測(cè)試類(lèi)。通過(guò)@Autowired注解對(duì) ElasticsearchTemplate進(jìn)?注?,測(cè)試對(duì)象是否可以獲取到。
package com.csdn.es; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.data.elasticsearch.core.ElasticsearchTemplate; import org.springframework.test.context.junit4.SpringRunner; @RunWith(SpringRunner.class) @SpringBootTest public class SpringDataESTests { @Autowired private ElasticsearchTemplate template; @Test public void check() { System.err.println(template); } }
注: 使用 Spring Data Elasticsearch 是springboot 版本不能太高,建議使用 2.1.6.RELEASE 版本。如果有 Rest Client 版本太高也會(huì)注入失敗,建議使用 6.4.3 。
2. 操作
2.1 索引庫(kù)操作
2.1.1 實(shí)體類(lèi)注解
1.我們?cè)赑roduct實(shí)體類(lèi)上添加下?的?些注解。
package com.csdn.pojo; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import org.springframework.data.annotation.Id; import org.springframework.data.elasticsearch.annotations.Document; import org.springframework.data.elasticsearch.annotations.Field; import org.springframework.data.elasticsearch.annotations.FieldType; @Data @NoArgsConstructor @AllArgsConstructor @Document(indexName = "csdn", type = "product", shards = 3, replicas = 1) public class Product { @Id private Long id; @Field(type = FieldType.Text, analyzer = "ik_max_word") private String title; // 標(biāo)題 @Field(type = FieldType.Keyword) private String category; // 分類(lèi) @Field(type = FieldType.Keyword) private String brand; // 品牌 @Field(type = FieldType.Double) private Double price; // 價(jià)格 @Field(type = FieldType.Keyword, index = false) private String images; // 圖?地址 }
2.在SpringDataESTests類(lèi)中定義創(chuàng)建索引的createIndex()?法。
@Test public void createIndex() { // 創(chuàng)建索引庫(kù),并制定實(shí)體類(lèi)的字節(jié)碼 template.createIndex(Product.class); }
2.1.2 創(chuàng)建映射
剛才的注解已經(jīng)把映射關(guān)系也配置上了,所以創(chuàng)建映射只需要這樣:
@Test public void createMapping() { template.putMapping(Product.class); }
2.2 索引數(shù)據(jù)CRUD操作
SDE的索引數(shù)據(jù)CRUD操作并沒(méi)有封裝在ElasticsearchTemplate類(lèi)中,?是有?個(gè)叫做ElasticsearchRepository的 接?中。
在com.csdn.respository包下?定義ProductRepository接?,并繼承ElasticsearchRespository接?。
package com.csdn.respository; import com.yx.pojo.Product; import org.springframework.data.elasticsearch.repository.ElasticsearchRepository; public interface ProductRepository extends ElasticsearchRepository<Product, Long> { }
2.2.1 創(chuàng)建索引數(shù)據(jù)
1.先來(lái)看單個(gè)創(chuàng)建。在SpringDataESTests類(lèi)中定義addDocument()?法。
@Autowired private ProductRepository productRepository; @Test public void addDocument() { Product product = new Product(1L, "???機(jī)Mix", "?機(jī)", "??", 2899.00, "http://image.yx.com/12479122.jpg"); // 添加索引數(shù)據(jù) productRepository.save(product); }
2.再來(lái)看批量創(chuàng)建。在SpringDataESTests類(lèi)中定義addDocuments()?法。
@Test public void addDocuments() { // 準(zhǔn)備?檔數(shù)據(jù) List<Product> list = new ArrayList<>(); list.add(new Product(2L, "堅(jiān)果?機(jī)R1", "?機(jī)", "錘?", 3699.00, "http://image.yx.com/12479122.jpg")); list.add(new Product(3L, "華為META20", "?機(jī)", "華為", 4499.00, "http://image.yx.com/12479122.jpg")); list.add(new Product(4L, "??Pro", "?機(jī)", "??", 4299.00, "http://image.yx.com/12479122.jpg")); list.add(new Product(5L, "榮耀V20", "?機(jī)", "華為", 2799.00, "http://image.yx.com/12479122.jpg")); // 添加索引數(shù)據(jù) productRepository.saveAll(list); }
2.2.2 查詢(xún)索引數(shù)據(jù)
1.根據(jù)id查詢(xún)數(shù)據(jù)
@Test public void findById() { Optional<Product> optional = productRepository.findById(1L); Product defaultProduct = new Product(); defaultProduct.setTitle("默認(rèn)商品數(shù)據(jù)"); // orElse(T other)?法:如果Optional對(duì)象中封裝的泛型為null,則將orElse()?法的參數(shù)作為返回值 Product product = optional.orElse(defaultProduct); System.err.println(product); }
2.查詢(xún)所有數(shù)據(jù)
@Test public void findAll() { Iterable<Product> list = productRepository.findAll(); list.forEach(System.err::println); }
2.2.3 ?定義?法查詢(xún)
在ProductRepository接?中定義根據(jù)商品的價(jià)格區(qū)間查詢(xún)商品數(shù)據(jù)的findByPriceBetween()?法。
/** * 根據(jù)商品的價(jià)格區(qū)間查詢(xún)商品數(shù)據(jù) * @param from 開(kāi)始價(jià)格 * @param to 結(jié)束價(jià)格 * @return 符合條件的商品數(shù)據(jù) */ List<Product> findByPriceBetween(Double from, Double to);
?需寫(xiě)實(shí)現(xiàn),SDE會(huì)?動(dòng)幫我們實(shí)現(xiàn)該?法,我們只需要?即可。在SpringDataESTests類(lèi)中定義 findByPriceBetween()?法。
@Test public void findByPriceBetween() { List<Product> products = productRepository.findByPriceBetween(3000d, 5000d); products.forEach(System.err::println); }
2.3 原?查詢(xún)案例
在com.csdn.mapper包下?定義搜索結(jié)果映射ProductSearchResultMapper類(lèi)。
package com.csdn.esclient; import com.google.gson.Gson; import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.search.SearchHit; import org.elasticsearch.search.SearchHits; import org.elasticsearch.common.text.Text; import org.elasticsearch.search.fetch.subphase.highlight.HighlightField; import org.springframework.data.domain.Pageable; import org.springframework.data.elasticsearch.core.SearchResultMapper; import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage; import org.springframework.data.elasticsearch.core.aggregation.impl.AggregatedPageImpl; import java.util.ArrayList; import java.util.List; import java.util.Map; /** * 1.接口 SearchResultMapper 表示用來(lái)自定義查詢(xún)結(jié)果映射,將結(jié)果按照開(kāi)發(fā)者的配置,進(jìn)行重組,然后返回客戶(hù)端 * 2.重寫(xiě) mapResults */ /** ?定義查詢(xún)結(jié)果映射,?于處理?亮顯示 */ public class ProductSearchResulMapper implements SearchResultMapper { @Override public <T> AggregatedPage<T> mapResults(SearchResponse searchResponse, Class<T> aClass, Pageable pageable) { // 記錄總條數(shù) long totalHits = searchResponse.getHits().getTotalHits(); // 記錄列表(泛型) - 構(gòu)建Aggregate使? List<T> list = new ArrayList<>(); // 獲取搜索結(jié)果(真正的的記錄) SearchHits hits = searchResponse.getHits(); Gson gson = new Gson(); for (SearchHit hit : hits) { if (hits.getHits().length <= 0) { return null; } // 將原本的JSON對(duì)象轉(zhuǎn)換成Map對(duì)象 Map<String, Object> map = hit.getSourceAsMap(); // 獲取?亮的字段Map Map<String, HighlightField> highlightFields = hit.getHighlightFields(); for (Map.Entry<String, HighlightField> highlightField : highlightFields.entrySet()) { // 獲取?亮的Key String key = highlightField.getKey(); // 獲取?亮的Value HighlightField value = highlightField.getValue(); // 實(shí)際fragments[0]就是?亮的結(jié)果,?需遍歷拼接 Text[] fragments = value.getFragments(); // 因?yàn)?亮的字段必然存在于Map中,就是key值 map.put(key, fragments[0].toString()); } // 把Map轉(zhuǎn)換成對(duì)象 T item = gson.fromJson(gson.toJson(map), aClass); list.add(item); } // 返回的是帶分?的結(jié)果 return new AggregatedPageImpl<>(list, pageable, totalHits); } }
Java測(cè)試類(lèi):
package com.csdn.es; import com.qf.esclient.ProductSearchResulMapper; import com.qf.pojo.Product; import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.search.aggregations.AggregationBuilders; import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Sort; import org.springframework.data.elasticsearch.core.ElasticsearchTemplate; import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage; import org.springframework.data.elasticsearch.core.query.FetchSourceFilter; import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder; import org.springframework.test.context.junit4.SpringRunner; import java.util.List; @SpringBootTest @RunWith(SpringRunner.class) public class SpringDataESTests { @Autowired private ElasticsearchTemplate template; @Test public void test01() { // 1.創(chuàng)建原生查詢(xún)語(yǔ)句構(gòu)建 NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder(); // 2.通過(guò)NativeSearchQueryBuilder指定過(guò)濾器條件 builder.withSourceFilter(new FetchSourceFilter(null,null)); // 3.添加詞條搜索條件 builder.withQuery(QueryBuilders.matchQuery("title","手機(jī)")); // 4.分頁(yè)操作:當(dāng)前頁(yè)其實(shí)位置的下標(biāo) builder.withPageable(PageRequest.of(0, 2, Sort.by(Sort.Direction.ASC, "price"))); // 5.高亮顯示 TODO HighlightBuilder.Field field = new HighlightBuilder.Field("title"); field.preTags("<span style='color:red'>"); field.postTags("</span>"); builder.withHighlightFields(field); // 6.聚合:分組。參數(shù)解析:terms()方法指定分組的名稱(chēng)(聚合名稱(chēng)) builder.addAggregation(AggregationBuilders.terms("brandAgg").field("brand")); // 7.構(gòu)建查詢(xún)的條件,并且執(zhí)行查詢(xún) AggregatedPage<Product> packages = template.queryForPage(builder.build(), Product.class,new ProductSearchResulMapper()); long total = packages.getTotalElements(); int totalPages = packages.getTotalPages(); List<Product> list = packages.getContent(); System.out.println("總條數(shù):" + total); System.out.println("總?數(shù):" + totalPages); System.out.println("數(shù)據(jù):"); list.forEach(System.out::println); // 聚合 /** Aggregations aggregations = packages.getAggregations(); // 導(dǎo)包org.elasticsearch.search.aggregations.bucket.terms.Terms Terms terms = aggregations.get("brandAgg"); terms.getBuckets().forEach(b -> { System.err.println("品牌:" + b.getKeyAsString()); System.err.println("count:" + b.getDocCount()); }); */ } }
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
- Springboot整合spring-boot-starter-data-elasticsearch的過(guò)程
- Spring?Data?Elasticsearch?5.x實(shí)現(xiàn)單詞糾錯(cuò)和自動(dòng)補(bǔ)全
- Spring?Data?Elasticsearch?5.0.x修改數(shù)據(jù)后無(wú)法立即刷新解決方法示例
- SpringData整合ElasticSearch實(shí)現(xiàn)CRUD的示例代碼(超詳細(xì))
- SpringDataElasticsearch與SpEL表達(dá)式實(shí)現(xiàn)ES動(dòng)態(tài)索引
- spring-data-elasticsearch @Field注解無(wú)效的完美解決方案
相關(guān)文章
springboot配置多數(shù)據(jù)源后mybatis攔截器失效的解決
這篇文章主要介紹了springboot配置多數(shù)據(jù)源后mybatis攔截器失效的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-09-09Maven最佳實(shí)踐之一個(gè)好的parent依賴(lài)基礎(chǔ)
今天小編就為大家分享一篇關(guān)于Maven最佳實(shí)踐之一個(gè)好的parent依賴(lài)基礎(chǔ),小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2018-12-12Spring ApplicationListener監(jiān)聽(tīng)器用法詳解
這篇文章主要介紹了Spring ApplicationListener監(jiān)聽(tīng)器用法詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-11-11使用springboot activiti關(guān)閉驗(yàn)證自動(dòng)部署方式
這篇文章主要介紹了使用springboot activiti關(guān)閉驗(yàn)證自動(dòng)部署方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-09-09玩轉(zhuǎn)spring boot 結(jié)合jQuery和AngularJs(3)
玩轉(zhuǎn)spring boot,這篇文章主要介紹了結(jié)合jQuery和AngularJs,玩轉(zhuǎn)spring boot,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-01-01Spring Boot項(xiàng)目中定制PropertyEditors方法
在本篇文章里小編給大家分享的是一篇關(guān)于Spring Boot定制PropertyEditors的知識(shí)點(diǎn)內(nèi)容,有需要的朋友們可以參考學(xué)習(xí)下。2019-11-11詳解JavaScript中的函數(shù)聲明和函數(shù)表達(dá)式
這篇文章主要介紹了詳解JavaScript中的函數(shù)聲明和函數(shù)表達(dá)式,是JS入門(mén)學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下2015-08-08Java并發(fā)編程 interrupt()方法示例詳解
interrrupt()方法可以用來(lái)打斷正在運(yùn)行的線(xiàn)程,也可以打斷sleep()、wait()、join()情況下的線(xiàn)程,但是這些情況下被打斷線(xiàn)程的打斷標(biāo)記不同,這篇文章主要介紹了Java并發(fā)編程 interrupt()方法示例詳解,需要的朋友可以參考下2023-06-06