Spring data elasticsearch使用方法詳解
這篇文章主要介紹了Spring data elasticsearch使用方法詳解,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
一、準備
1.添加依賴
<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.實體類
@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 作用在類,標記實體類為文檔對象,一般有兩個屬性
- indexName:對應(yīng)索引庫名稱
- type:對應(yīng)在索引庫中的類型
- shards:分片數(shù)量,默認5
- replicas:副本數(shù)量,默認1
- @Id 作用在成員變量,標記一個字段作為id主鍵
- @Field 作用在成員變量,標記為文檔的字段,并指定字段映射屬性:
- type:字段類型,取值是枚舉:FieldType
- index:是否索引,布爾類型,默認是true
- store:是否存儲,布爾類型,默認是false
- analyzer:分詞器名稱
二.、索引操作
首先注入ElasticsearchTemplate
@Resource private ElasticsearchTemplate elasticsearchTemplate;
● 創(chuàng)建索引
elasticsearchTemplate.createIndex(Goods.class);
● 配置映射
elasticsearchTemplate.putMapping(Goods.class);
● 刪除索引
//根據(jù)類
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, "小米手機7", " 手機",
"小米", 3499.00, "http://image.leyou.com/13123.jpg");
itemRepository.save(item);
● 批量新增
List<Item> list = new ArrayList<>(); list.add(new Item(2L, "堅果手機R1", " 手機", "錘子", 3699.00, "http://image.leyou.com/123.jpg")); list.add(new Item(3L, "華為META10", " 手機", "華為", 4499.00, "http://image.leyou.com/3.jpg")); // 接收對象集合,實現(xiàn)批量新增 itemRepository.saveAll(list);
四、 基本搜索
● 基本查詢。

例:
// 查詢?nèi)?,并安裝價格降序排序 Iterable<Item> items = this.itemRepository.findAll(Sort.by(Sort.Direction.DESC, "price")); items.forEach(item-> System.out.println(item));
● 自定義查詢
| 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ù)價格區(qū)間查詢
* @param price1
* @param price2
* @return
*/
List<Item> findByPriceBetween(double price1, double price2);
}
五、高級查詢
● 詞條查詢
MatchQueryBuilder queryBuilder = QueryBuilders.matchQuery("all", "小米");
// 執(zhí)行查詢
Iterable<Goods> goods = this.goodsRepository.search(queryBuilder);
● 自定義查詢
// 構(gòu)建查詢條件
NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
// 添加基本的分詞查詢
queryBuilder.withQuery(QueryBuilders.matchQuery("all", "小米"));
// 執(zhí)行搜索,獲取結(jié)果
Page<Goods> goods = this.goodsRepository.search(queryBuilder.build());
// 打印總條數(shù)
System.out.println(goods.getTotalElements());
// 打印總頁數(shù)
System.out.println(goods.getTotalPages());
● 分頁查詢
// 構(gòu)建查詢條件
NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
// 添加基本的分詞查詢
queryBuilder.withQuery(QueryBuilders.termQuery("all", "手機"));
// 初始化分頁參數(shù)
int page = 0;
int size = 3;
// 設(shè)置分頁參數(shù)
queryBuilder.withPageable(PageRequest.of(page, size));
// 執(zhí)行搜索,獲取結(jié)果
Page<Goods> goods = this.goodsRepository.search(queryBuilder.build());
// 打印總條數(shù)
System.out.println(goods.getTotalElements());
// 打印總頁數(shù)
System.out.println(goods.getTotalPages());
// 每頁大小
System.out.println(goods.getSize());
// 當(dāng)前頁
System.out.println(goods.getNumber());
● 排序
// 構(gòu)建查詢條件
NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
// 添加基本的分詞查詢
queryBuilder.withQuery(QueryBuilders.termQuery("all", "手機"));
// 排序
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();
// 不查詢?nèi)魏谓Y(jié)果
queryBuilder.withSourceFilter(new FetchSourceFilter(new String[]{""}, null));
// 1、添加一個新的聚合,聚合類型為terms,聚合名稱為brands,聚合字段為brand
queryBuilder.addAggregation(AggregationBuilders.terms("brands").field("brandId"));
// 2、查詢,需要把結(jié)果強轉(zhuǎn)為AggregatedPage類型
AggregatedPage<Goods> aggPage = (AggregatedPage<Goods>) this.goodsRepository.search(queryBuilder.build());
// 3、解析
// 3.1、從結(jié)果中取出名為brands的那個聚合,
// 因為是利用String類型字段來進行的term聚合,所以結(jié)果要強轉(zhuǎn)為StringTerm類型
LongTerms agg = (LongTerms) aggPage.getAggregation("brands");
// 3.2、獲取桶
List<LongTerms.Bucket> buckets = agg.getBuckets();
// 3.3、遍歷
for (LongTerms.Bucket bucket : buckets) {
// 3.4、獲取桶中的key,即品牌名稱
System.out.println(bucket.getKeyAsString());
// 3.5、獲取桶中的文檔數(shù)量
System.out.println(bucket.getDocCount());
}
● 嵌套聚合,求平均值
NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
// 不查詢?nèi)魏谓Y(jié)果
queryBuilder.withSourceFilter(new FetchSourceFilter(new String[]{""}, null));
// 1、添加一個新的聚合,聚合類型為terms,聚合名稱為brands,聚合字段為brand
queryBuilder.addAggregation(AggregationBuilders.terms("brands").field("brandId")
.subAggregation(AggregationBuilders.avg("priceAvg").field("price"))); // 在品牌聚合桶內(nèi)進行嵌套聚合,求平均值
// 2、查詢,需要把結(jié)果強轉(zhuǎn)為AggregatedPage類型
AggregatedPage<Goods> aggPage = (AggregatedPage<Goods>) this.goodsRepository.search(queryBuilder.build());
// 3、解析
// 3.1、從結(jié)果中取出名為brands的那個聚合,
// 因為是利用String類型字段來進行的term聚合,所以結(jié)果要強轉(zhuǎn)為StringTerm類型
LongTerms agg = (LongTerms) aggPage.getAggregation("brands");
// 3.2、獲取桶
List<LongTerms.Bucket> buckets = agg.getBuckets();
// 3.3、遍歷
for (LongTerms.Bucket bucket : buckets) {
// 3.4、獲取桶中的key,即品牌名稱 3.5、獲取桶中的文檔數(shù)量
System.out.println(bucket.getKeyAsString() + ",共" + bucket.getDocCount() + "臺");
// 3.6.獲取子聚合結(jié)果:
InternalAvg avg = (InternalAvg) bucket.getAggregations().asMap().get("priceAvg");
System.out.println("平均售價:" + avg.getValue());
}
附:配置搜索結(jié)果不顯示為null字段:
spring: jackson: default-property-inclusion: non_null # 配置json處理時忽略空值
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Java數(shù)據(jù)結(jié)構(gòu)之棧的線性結(jié)構(gòu)詳解
從數(shù)據(jù)結(jié)構(gòu)上看棧和隊列都是線性表,不過是兩種特殊的線性表,棧只允許在的一端進行插人或刪除操作,而隊列只允許在表的一端進行插人操作、而在另一端進行刪除操作,這篇文章主要給大家介紹了關(guān)于Java數(shù)據(jù)結(jié)構(gòu)之棧的線性結(jié)構(gòu)的相關(guān)資料,需要的朋友可以參考下2021-08-08
Java基于API接口爬取商品數(shù)據(jù)的示例代碼
Java作為一種流行的編程語言,可以用于編寫程序來調(diào)用這些API接口,從而獲取商品數(shù)據(jù),本文將介紹如何使用Java基于API接口爬取商品數(shù)據(jù),包括請求API、解析JSON數(shù)據(jù)、存儲數(shù)據(jù)等步驟,并提供相應(yīng)的代碼示例,感興趣的朋友跟隨小編一起看看吧2023-10-10
idea2019版與maven3.6.2版本不兼容的解決方法
這篇文章主要介紹了idea2019版與maven3.6.2版本不兼容的解決方法,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-10-10
Java 多線程等待優(yōu)雅的實現(xiàn)方式之Phaser同步屏障
在JAVA 1.7引入了一個新的并發(fā)API:Phaser,一個可重用的同步barrier。在此前,JAVA已經(jīng)有CyclicBarrier、CountDownLatch這兩種同步barrier,但是Phaser更加靈活,而且側(cè)重于 重用2021-11-11
Java使用POI導(dǎo)出大數(shù)據(jù)量Excel的方法
今天需要寫一個導(dǎo)出的Excel的功能,但是發(fā)現(xiàn)當(dāng)數(shù)據(jù)量到3萬條時,列數(shù)在23列時,內(nèi)存溢出,CPU使用100%,測試環(huán)境直接炸掉。小編給大家分享基于java使用POI導(dǎo)出大數(shù)據(jù)量Excel的方法,感興趣的朋友一起看看吧2019-11-11
java.lang.AbstractMethodError: org.apache.xerces.dom.Documen
這篇文章主要介紹了java.lang.AbstractMethodError: org.apache.xerces.dom.DocumentImpl.setXmlVersion問題解決方法,導(dǎo)致本文問題的原因是缺少一個xerces.jar jar包,需要的朋友可以參考下2015-03-03

