1. 项目部署

 

1.1 添加依赖 

在项目的 pom.xml 中引⼊Spring Data Elasticsearch的启动器。

org.springframework.boot

spring-boot-starter-data-elasticsearch

 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协议通信,⽽是访问Elasticsearch对外开放的TCP端⼝。我们在之前集群配置 中,设置的端⼝分别是:9301、9302、9303。

 1.3 测试是否注入成功

在test测试⽂件夹下的com.csdn.es包下创建⼀个SpringDataESTests测试类。通过@Autowired注解对 ElasticsearchTemplate进⾏注⼊,测试对象是否可以获取到。 

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 版本太高也会注入失败,建议使用 6.4.3 。

 2. 操作

2.1 索引库操作

2.1.1 实体类注解 

1.我们在Product实体类上添加下⾯的⼀些注解。

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; // 标题

@Field(type = FieldType.Keyword)

private String category; // 分类

@Field(type = FieldType.Keyword)

private String brand; // 品牌

@Field(type = FieldType.Double)

private Double price; // 价格

@Field(type = FieldType.Keyword, index = false)

private String images; // 图⽚地址

}

 2.在SpringDataESTests类中定义创建索引的createIndex()⽅法。

@Test

public void createIndex() {

// 创建索引库,并制定实体类的字节码

template.createIndex(Product.class);

}

 2.1.2 创建映射

刚才的注解已经把映射关系也配置上了,所以创建映射只需要这样: 

@Test

public void createMapping() {

template.putMapping(Product.class);

}

 2.2 索引数据CRUD操作

SDE的索引数据CRUD操作并没有封装在ElasticsearchTemplate类中,⽽是有⼀个叫做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 {

}

2.2.1 创建索引数据

1.先来看单个创建。在SpringDataESTests类中定义addDocument()⽅法。

@Autowired

private ProductRepository productRepository;

@Test

public void addDocument() {

Product product = new Product(1L, "⼩⽶⼿机Mix", "⼿机", "⼩⽶", 2899.00,

"http://image.yx.com/12479122.jpg");

// 添加索引数据

productRepository.save(product);

}

 2.再来看批量创建。在SpringDataESTests类中定义addDocuments()⽅法。

@Test

public void addDocuments() {

// 准备⽂档数据

List list = new ArrayList<>();

list.add(new Product(2L, "坚果⼿机R1", "⼿机", "锤⼦", 3699.00,

"http://image.yx.com/12479122.jpg"));

list.add(new Product(3L, "华为META20", "⼿机", "华为", 4499.00,

"http://image.yx.com/12479122.jpg"));

list.add(new Product(4L, "⼩⽶Pro", "⼿机", "⼩⽶", 4299.00,

"http://image.yx.com/12479122.jpg"));

list.add(new Product(5L, "荣耀V20", "⼿机", "华为", 2799.00,

"http://image.yx.com/12479122.jpg"));

// 添加索引数据

productRepository.saveAll(list);

}

 2.2.2 查询索引数据

1.根据id查询数据 

@Test

public void findById() {

Optional optional = productRepository.findById(1L);

Product defaultProduct = new Product();

defaultProduct.setTitle("默认商品数据");

// orElse(T other)⽅法:如果Optional对象中封装的泛型为null,则将orElse()⽅法的参数作为返回值

Product product = optional.orElse(defaultProduct);

System.err.println(product);

}

 2.查询所有数据

@Test

public void findAll() {

Iterable list = productRepository.findAll();

list.forEach(System.err::println);

}

2.2.3  ⾃定义⽅法查询

在ProductRepository接⼝中定义根据商品的价格区间查询商品数据的findByPriceBetween()⽅法。 

/**

* 根据商品的价格区间查询商品数据

* @param from 开始价格

* @param to 结束价格

* @return 符合条件的商品数据

*/

List findByPriceBetween(Double from, Double to);

⽆需写实现,SDE会⾃动帮我们实现该⽅法,我们只需要⽤即可。在SpringDataESTests类中定义 findByPriceBetween()⽅法。

@Test

public void findByPriceBetween() {

List products = productRepository.findByPriceBetween(3000d, 5000d);

products.forEach(System.err::println);

}

 2.3 原⽣查询案例

在com.csdn.mapper包下⾃定义搜索结果映射ProductSearchResultMapper类。

 

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 表示用来自定义查询结果映射,将结果按照开发者的配置,进行重组,然后返回客户端

* 2.重写 mapResults

*/

/** ⾃定义查询结果映射,⽤于处理⾼亮显示 */

public class ProductSearchResulMapper implements SearchResultMapper {

@Override

public AggregatedPage mapResults(SearchResponse searchResponse, Class aClass, Pageable pageable) {

// 记录总条数

long totalHits = searchResponse.getHits().getTotalHits();

// 记录列表(泛型) - 构建Aggregate使⽤

List list = new ArrayList<>();

// 获取搜索结果(真正的的记录)

SearchHits hits = searchResponse.getHits();

Gson gson = new Gson();

for (SearchHit hit : hits) {

if (hits.getHits().length <= 0) {

return null;

}

// 将原本的JSON对象转换成Map对象

Map map = hit.getSourceAsMap();

// 获取⾼亮的字段Map

Map highlightFields = hit.getHighlightFields();

for (Map.Entry highlightField : highlightFields.entrySet()) {

// 获取⾼亮的Key

String key = highlightField.getKey();

// 获取⾼亮的Value

HighlightField value = highlightField.getValue();

// 实际fragments[0]就是⾼亮的结果,⽆需遍历拼接

Text[] fragments = value.getFragments();

// 因为⾼亮的字段必然存在于Map中,就是key值

map.put(key, fragments[0].toString());

}

// 把Map转换成对象

T item = gson.fromJson(gson.toJson(map), aClass);

list.add(item);

}

// 返回的是带分⻚的结果

return new AggregatedPageImpl<>(list, pageable, totalHits);

}

}

Java测试类: 

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.创建原生查询语句构建

NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();

// 2.通过NativeSearchQueryBuilder指定过滤器条件

builder.withSourceFilter(new FetchSourceFilter(null,null));

// 3.添加词条搜索条件

builder.withQuery(QueryBuilders.matchQuery("title","手机"));

// 4.分页操作:当前页其实位置的下标

builder.withPageable(PageRequest.of(0, 2, Sort.by(Sort.Direction.ASC,

"price")));

// 5.高亮显示 TODO

HighlightBuilder.Field field = new HighlightBuilder.Field("title");

field.preTags("");

field.postTags("");

builder.withHighlightFields(field);

// 6.聚合:分组。参数解析:terms()方法指定分组的名称(聚合名称)

builder.addAggregation(AggregationBuilders.terms("brandAgg").field("brand"));

// 7.构建查询的条件,并且执行查询

AggregatedPage packages = template.queryForPage(builder.build(), Product.class,new ProductSearchResulMapper());

long total = packages.getTotalElements();

int totalPages = packages.getTotalPages();

List list = packages.getContent();

System.out.println("总条数:" + total);

System.out.println("总⻚数:" + totalPages);

System.out.println("数据:");

list.forEach(System.out::println);

// 聚合

/**

Aggregations aggregations = packages.getAggregations();

// 导包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());

});

*/

}

}

 

好文链接

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: