Spring data elasticsearch使用方法詳解
這篇文章主要介紹了Spring data elasticsearch使用方法詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
一、準(zhǔn)備
1.添加依賴(lài)
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-elasticsearch</artifactId> </dependency>
2.application.yml
spring: application: name: search-service data: elasticsearch: cluster-name: elasticsearch cluster-nodes: 192.168.25.129:9300
3.實(shí)體類(lèi)
@Data @Document(indexName = "goods", type = "_doc", shards = 1, replicas = 0) public class Goods { @Idprivate Long id; @Field(type = FieldType.text, analyzer = "ik_max_word") private String all; @Field(type = FieldType.keyword, index = false) private String subTitle;private Long brandId;private Long cid1;private Long cid2;private Long cid3;private Date createTime;private List<Long> price; @Field(type = FieldType.keyword, index = false) private String skus;private Map<String, Object> specs; }
@Document 作用在類(lèi),標(biāo)記實(shí)體類(lèi)為文檔對(duì)象,一般有兩個(gè)屬性
- indexName:對(duì)應(yīng)索引庫(kù)名稱(chēng)
- type:對(duì)應(yīng)在索引庫(kù)中的類(lèi)型
- shards:分片數(shù)量,默認(rèn)5
- replicas:副本數(shù)量,默認(rèn)1
- @Id 作用在成員變量,標(biāo)記一個(gè)字段作為id主鍵
- @Field 作用在成員變量,標(biāo)記為文檔的字段,并指定字段映射屬性:
- type:字段類(lèi)型,取值是枚舉:FieldType
- index:是否索引,布爾類(lèi)型,默認(rèn)是true
- store:是否存儲(chǔ),布爾類(lèi)型,默認(rèn)是false
- analyzer:分詞器名稱(chēng)
二.、索引操作
首先注入ElasticsearchTemplate
@Resource private ElasticsearchTemplate elasticsearchTemplate;
● 創(chuàng)建索引
elasticsearchTemplate.createIndex(Goods.class);
● 配置映射
elasticsearchTemplate.putMapping(Goods.class);
● 刪除索引
//根據(jù)類(lèi) elasticsearchTemplate.deleteIndex(Goods.class); //根據(jù)索引名 elasticsearchTemplate.deleteIndex("goods");
三、文檔操作
1.定義接口。也是SpringData風(fēng)格
public interface ItemRepository extends ElasticsearchRepository<Item,Long> { }
2.注入
@Autowired private ItemRepository itemRepository;
● 新增文檔
Item item = new Item(1L, "小米手機(jī)7", " 手機(jī)", "小米", 3499.00, "http://image.leyou.com/13123.jpg"); itemRepository.save(item);
● 批量新增
List<Item> list = new ArrayList<>(); list.add(new Item(2L, "堅(jiān)果手機(jī)R1", " 手機(jī)", "錘子", 3699.00, "http://image.leyou.com/123.jpg")); list.add(new Item(3L, "華為META10", " 手機(jī)", "華為", 4499.00, "http://image.leyou.com/3.jpg")); // 接收對(duì)象集合,實(shí)現(xiàn)批量新增 itemRepository.saveAll(list);
四、 基本搜索
● 基本查詢(xún)。
例:
// 查詢(xún)?nèi)?,并安裝價(jià)格降序排序 Iterable<Item> items = this.itemRepository.findAll(Sort.by(Sort.Direction.DESC, "price")); items.forEach(item-> System.out.println(item));
● 自定義查詢(xún)
Keyword | Sample | Elasticsearch Query String |
---|---|---|
And | findByNameAndPrice | {"bool" : {"must" : [ {"field" : {"name" : "?"}}, {"field" : {"price" : "?"}} ]}} |
Or | findByNameOrPrice | {"bool" : {"should" : [ {"field" : {"name" : "?"}}, {"field" : {"price" : "?"}} ]}} |
Is | findByName | {"bool" : {"must" : {"field" : {"name" : "?"}}}} |
Not | findByNameNot | {"bool" : {"must_not" : {"field" : {"name" : "?"}}}} |
Between | findByPriceBetween | {"bool" : {"must" : {"range" : {"price" : {"from" : ?,"to" : ?,"include_lower" : true,"include_upper" : true}}}}} |
LessThanEqual | findByPriceLessThan | {"bool" : {"must" : {"range" : {"price" : {"from" : null,"to" : ?,"include_lower" : true,"include_upper" : true}}}}} |
GreaterThanEqual | findByPriceGreaterThan | {"bool" : {"must" : {"range" : {"price" : {"from" : ?,"to" : null,"include_lower" : true,"include_upper" : true}}}}} |
Before | findByPriceBefore | {"bool" : {"must" : {"range" : {"price" : {"from" : null,"to" : ?,"include_lower" : true,"include_upper" : true}}}}} |
After | findByPriceAfter | {"bool" : {"must" : {"range" : {"price" : {"from" : ?,"to" : null,"include_lower" : true,"include_upper" : true}}}}} |
Like | findByNameLike | {"bool" : {"must" : {"field" : {"name" : {"query" : "?*","analyze_wildcard" : true}}}}} |
StartingWith | findByNameStartingWith | {"bool" : {"must" : {"field" : {"name" : {"query" : "?*","analyze_wildcard" : true}}}}} |
EndingWith | findByNameEndingWith | {"bool" : {"must" : {"field" : {"name" : {"query" : "*?","analyze_wildcard" : true}}}}} |
Contains/Containing | findByNameContaining | {"bool" : {"must" : {"field" : {"name" : {"query" : "**?**","analyze_wildcard" : true}}}}} |
In | findByNameIn(Collection<String>names) | {"bool" : {"must" : {"bool" : {"should" : [ {"field" : {"name" : "?"}}, {"field" : {"name" : "?"}} ]}}}} |
NotIn | findByNameNotIn(Collection<String>names) | {"bool" : {"must_not" : {"bool" : {"should" : {"field" : {"name" : "?"}}}}}} |
Near | findByStoreNear | Not Supported Yet ! |
True | findByAvailableTrue | {"bool" : {"must" : {"field" : {"available" : true}}}} |
False | findByAvailableFalse | {"bool" : {"must" : {"field" : {"available" : false}}}} |
OrderBy | findByAvailableTrueOrderByNameDesc | {"sort" : [{ "name" : {"order" : "desc"} }],"bool" : {"must" : {"field" : {"available" : true}}}} |
例:
public interface ItemRepository extends ElasticsearchRepository<Item,Long> { /** * 根據(jù)價(jià)格區(qū)間查詢(xún) * @param price1 * @param price2 * @return */ List<Item> findByPriceBetween(double price1, double price2); }
五、高級(jí)查詢(xún)
● 詞條查詢(xún)
MatchQueryBuilder queryBuilder = QueryBuilders.matchQuery("all", "小米"); // 執(zhí)行查詢(xún) Iterable<Goods> goods = this.goodsRepository.search(queryBuilder);
● 自定義查詢(xún)
// 構(gòu)建查詢(xún)條件 NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder(); // 添加基本的分詞查詢(xún) queryBuilder.withQuery(QueryBuilders.matchQuery("all", "小米")); // 執(zhí)行搜索,獲取結(jié)果 Page<Goods> goods = this.goodsRepository.search(queryBuilder.build()); // 打印總條數(shù) System.out.println(goods.getTotalElements()); // 打印總頁(yè)數(shù) System.out.println(goods.getTotalPages());
● 分頁(yè)查詢(xún)
// 構(gòu)建查詢(xún)條件 NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder(); // 添加基本的分詞查詢(xún) queryBuilder.withQuery(QueryBuilders.termQuery("all", "手機(jī)")); // 初始化分頁(yè)參數(shù) int page = 0; int size = 3; // 設(shè)置分頁(yè)參數(shù) queryBuilder.withPageable(PageRequest.of(page, size)); // 執(zhí)行搜索,獲取結(jié)果 Page<Goods> goods = this.goodsRepository.search(queryBuilder.build()); // 打印總條數(shù) System.out.println(goods.getTotalElements()); // 打印總頁(yè)數(shù) System.out.println(goods.getTotalPages()); // 每頁(yè)大小 System.out.println(goods.getSize()); // 當(dāng)前頁(yè) System.out.println(goods.getNumber());
● 排序
// 構(gòu)建查詢(xún)條件 NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder(); // 添加基本的分詞查詢(xún) queryBuilder.withQuery(QueryBuilders.termQuery("all", "手機(jī)")); // 排序 queryBuilder.withSort(SortBuilders.fieldSort("price").order(SortOrder.DESC)); // 執(zhí)行搜索,獲取結(jié)果 Page<Goods> goods = this.goodsRepository.search(queryBuilder.build()); // 打印總條數(shù) System.out.println(goods.getTotalElements());
● 聚合為桶
NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder(); // 不查詢(xún)?nèi)魏谓Y(jié)果 queryBuilder.withSourceFilter(new FetchSourceFilter(new String[]{""}, null)); // 1、添加一個(gè)新的聚合,聚合類(lèi)型為terms,聚合名稱(chēng)為brands,聚合字段為brand queryBuilder.addAggregation(AggregationBuilders.terms("brands").field("brandId")); // 2、查詢(xún),需要把結(jié)果強(qiáng)轉(zhuǎn)為AggregatedPage類(lèi)型 AggregatedPage<Goods> aggPage = (AggregatedPage<Goods>) this.goodsRepository.search(queryBuilder.build()); // 3、解析 // 3.1、從結(jié)果中取出名為brands的那個(gè)聚合, // 因?yàn)槭抢肧tring類(lèi)型字段來(lái)進(jìn)行的term聚合,所以結(jié)果要強(qiáng)轉(zhuǎn)為StringTerm類(lèi)型 LongTerms agg = (LongTerms) aggPage.getAggregation("brands"); // 3.2、獲取桶 List<LongTerms.Bucket> buckets = agg.getBuckets(); // 3.3、遍歷 for (LongTerms.Bucket bucket : buckets) { // 3.4、獲取桶中的key,即品牌名稱(chēng) System.out.println(bucket.getKeyAsString()); // 3.5、獲取桶中的文檔數(shù)量 System.out.println(bucket.getDocCount()); }
● 嵌套聚合,求平均值
NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder(); // 不查詢(xún)?nèi)魏谓Y(jié)果 queryBuilder.withSourceFilter(new FetchSourceFilter(new String[]{""}, null)); // 1、添加一個(gè)新的聚合,聚合類(lèi)型為terms,聚合名稱(chēng)為brands,聚合字段為brand queryBuilder.addAggregation(AggregationBuilders.terms("brands").field("brandId") .subAggregation(AggregationBuilders.avg("priceAvg").field("price"))); // 在品牌聚合桶內(nèi)進(jìn)行嵌套聚合,求平均值 // 2、查詢(xún),需要把結(jié)果強(qiáng)轉(zhuǎn)為AggregatedPage類(lèi)型 AggregatedPage<Goods> aggPage = (AggregatedPage<Goods>) this.goodsRepository.search(queryBuilder.build()); // 3、解析 // 3.1、從結(jié)果中取出名為brands的那個(gè)聚合, // 因?yàn)槭抢肧tring類(lèi)型字段來(lái)進(jìn)行的term聚合,所以結(jié)果要強(qiáng)轉(zhuǎn)為StringTerm類(lèi)型 LongTerms agg = (LongTerms) aggPage.getAggregation("brands"); // 3.2、獲取桶 List<LongTerms.Bucket> buckets = agg.getBuckets(); // 3.3、遍歷 for (LongTerms.Bucket bucket : buckets) { // 3.4、獲取桶中的key,即品牌名稱(chēng) 3.5、獲取桶中的文檔數(shù)量 System.out.println(bucket.getKeyAsString() + ",共" + bucket.getDocCount() + "臺(tái)"); // 3.6.獲取子聚合結(jié)果: InternalAvg avg = (InternalAvg) bucket.getAggregations().asMap().get("priceAvg"); System.out.println("平均售價(jià):" + avg.getValue()); }
附:配置搜索結(jié)果不顯示為null字段:
spring: jackson: default-property-inclusion: non_null # 配置json處理時(shí)忽略空值
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Java volatile的適用場(chǎng)景實(shí)例詳解
在本文里我們給大家整理了一篇關(guān)于Java volatile的適用場(chǎng)景實(shí)例內(nèi)容和知識(shí)點(diǎn),需要的朋友們可以學(xué)習(xí)下。2019-08-08JVM?運(yùn)行時(shí)數(shù)據(jù)區(qū)與JMM?內(nèi)存模型
這篇文章主要介紹了JVM?運(yùn)行時(shí)數(shù)據(jù)區(qū)與JMM?內(nèi)存模型,文章圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值。需要的朋友可以參考一下2022-07-07idea配置檢查XML中SQL語(yǔ)法及書(shū)寫(xiě)sql語(yǔ)句智能提示的方法
idea連接了數(shù)據(jù)庫(kù),也可以執(zhí)行SQL查到數(shù)據(jù),但是無(wú)法識(shí)別sql語(yǔ)句中的表導(dǎo)致沒(méi)有提示,下面這篇文章主要給大家介紹了關(guān)于idea配置檢查XML中SQL語(yǔ)法及書(shū)寫(xiě)sql語(yǔ)句智能提示的相關(guān)資料,需要的朋友可以參考下2023-03-03Spring Boot + Thymeleaf + Activiti 快速開(kāi)發(fā)平臺(tái)項(xiàng)目 附源碼
這篇文章主要介紹了Spring Boot + Thymeleaf + Activiti 快速開(kāi)發(fā)平臺(tái)項(xiàng)目附源碼,代碼簡(jiǎn)單易懂,對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-04-04淺談ThreadLocal為什么會(huì)內(nèi)存泄漏
這篇文章主要介紹了淺談ThreadLocal為什么會(huì)內(nèi)存泄漏,每個(gè)Thread內(nèi)部維護(hù)著一個(gè)ThreadLocalMap,它是一個(gè)Map,這個(gè)映射表的Key是一個(gè)弱引用,其實(shí)就是ThreadLocal本身,Value是真正存的線程變量Object,需要的朋友可以參考下2023-12-12java實(shí)現(xiàn)學(xué)生成績(jī)錄入系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)學(xué)生成績(jī)錄入系統(tǒng),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-01-01