3.1、环境准备
1、添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
2、创建引导类
@SpringBootApplication
public class ESApplication {
public static void main(String[] args) {
SpringApplication.run(ESApplication.class,args);
}
}
3、配置文件 yml
spring:
data:
elasticsearch:
cluster-name: leyou-elastic
cluster-nodes: 127.0.0.1:9301,127.0.0.1:9302,127.0.0.1:9303
4、测试类 (注意所在包的位置)
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringDataEsTest {
}
5、准备一个实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
@Document(indexName = "leyou",type = "goods",shards = 3,replicas = 1)
public class Goods {
@Field(type= FieldType.Keyword)
private String id; //不分词
@Field(type= FieldType.Text,analyzer = "ik_max_word",index = true,store = true)
private String title; //标题 分词
@Field(type= FieldType.Keyword,index = true,store = true)
private String category;// 分类 不分词
@Field(type= FieldType.Keyword,index = true,store = true)
private String brand; // 品牌 不分词
@Field(type= FieldType.Double,index = true,store = true)
private Double price; // 价格 不分词
@Field(type= FieldType.Keyword,index = true,store = true)
private String images; // 图片地址 不分词
}
3.2、操作索引库和映射
在测试类中添加两个测试方法
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringDataEsTest {
@Autowired
private ElasticsearchTemplate esTemplate;
// 根据Goods中的注解的配置生成索引库
@Test
public void testAddIndex(){
esTemplate.createIndex(Goods.class);
}
// 根据Goods中的注解的配置生成mapping映射
@Test
public void testAddMapping(){
esTemplate.putMapping(Goods.class);
}
}
3.3、操作文档
需要我们自定义个接口
public interface GoodsRepository extends ElasticsearchRepository<Goods,String> {
}
@Autowired
private GoodsRepository goodsRepository;
@Test
public void testAddDoc(){
Goods goods = new Goods("1","小米9999手机","手机","小米",1199.0,"q3311");
goodsRepository.save(goods); // 有新增和修改的功能
}
@Test
public void testdeleteDoc(){
//goodsRepository.deleteAll(); // 慎用
goodsRepository.deleteById("1");
}
批量新增
@Test
public void testAddBulkDoc(){
List<Goods> list = new ArrayList<>();
list.add(new Goods("1", "小米手机7", "手机", "小米", 3299.00,"http://image.leyou.com/13123.jpg"));
list.add(new Goods("2", "坚果手机R1", "手机", "锤子", 3699.00,"http://image.leyou.com/13123.jpg"));
list.add(new Goods("3", "华为META10", "手机", "华为", 4499.00,"http://image.leyou.com/13123.jpg"));
list.add(new Goods("4", "小米Mix2S", "手机", "小米", 4299.00, "http://image.leyou.com/13123.jpg"));
list.add(new Goods("5", "荣耀V10", "手机", "华为", 2799.00,"http://image.leyou.com/13123.jpg"));
goodsRepository.saveAll(list);
}
3.4、查询
自定义查询方法
第一步:在接口中定义方法
public interface GoodsRepository extends ElasticsearchRepository<Goods,String> {
List<Goods> findByTitle(String title);
List<Goods> findByBrand(String brand);
List<Goods> findByPriceBetween(double v, double v1);
List<Goods> findByBrandAndPriceBetween(String brand, double v, double v1);
List<Goods> findByBrandOrPriceBetween(String brand, double v, double v1);
}
使用方法:
@Test
public void testSearch(){
// List<Goods> goodsList = goodsRepository.findByTitle("小米");
// List<Goods> goodsList = goodsRepository.findByBrand("小米");
// List<Goods> goodsList = goodsRepository.findByPriceBetween(2000.0,5000.0);
// List<Goods> goodsList = goodsRepository.findByBrandAndPriceBetween("小米",2000.0,5000.0);
List<Goods> goodsList = goodsRepository.findByBrandOrPriceBetween("小米",2000.0,5000.0);
goodsList.forEach(goods -> {
System.out.println(goods);
});
}
3.5、SDE结合原生查询
@Test
public void testQuery(){
NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
// nativeSearchQueryBuilder.withQuery(QueryBuilders.termQuery("title","华为"));
nativeSearchQueryBuilder.withQuery(QueryBuilders.matchAllQuery());
nativeSearchQueryBuilder.withPageable( PageRequest.of(0,2)); //分页
// 聚合条件
nativeSearchQueryBuilder.addAggregation( AggregationBuilders.terms("brandCount").field("brand"));
// SearchQuery query
AggregatedPage<Goods> aggregatedPage = esTemplate.queryForPage(nativeSearchQueryBuilder.build(), Goods.class);
// 获取聚合的结果
Terms terms = aggregatedPage.getAggregations().get("brandCount");
List<? extends Terms.Bucket> buckets = terms.getBuckets();
buckets.forEach(bucket->{
System.out.println( bucket.getKeyAsString()+":"+bucket.getDocCount());
});
// List<Goods> goodsList = aggregatedPage.getContent(); //获取数据的集合
// goodsList.forEach(goods -> {
// System.out.println(goods);
// });
}
3.6、自定义高亮结果
第一步:需要定义一个处理高亮的类
public class SearchResultMapperImpl implements SearchResultMapper{
@Override
public <T> AggregatedPage<T> mapResults(SearchResponse response, Class<T> clazz, Pageable pageable) {
long total = response.getHits().getTotalHits(); //返回时需要的参数
Aggregations aggregations = response.getAggregations(); //返回时需要的参数
String scrollId = response.getScrollId(); //返回时需要的参数
float maxScore = response.getHits().getMaxScore(); //返回时需要的参数
// 处理我们想要的高亮结果
SearchHit[] hits = response.getHits().getHits();
List<T> content = new ArrayList<>();
for (SearchHit hit : hits) {
String jsonString = hit.getSourceAsString();
T t = JSON.parseObject(jsonString, clazz);
Map<String, HighlightField> highlightFields = hit.getHighlightFields();
HighlightField highlightField = highlightFields.get("title");
Text[] fragments = highlightField.getFragments();
if(fragments!=null&&fragments.length>0){
String title = fragments[0].toString();
try {
// 把T对象中的 “title”属性的值替换成 title
BeanUtils.copyProperty(t,"title",title); // t.setTitle(title);
} catch (Exception e) {
// e.printStackTrace();
System.out.println("SSSSSSSS");
}
}
content.add(t);
}
return new AggregatedPageImpl<T>(content, pageable, total, aggregations, scrollId, maxScore);
}
}
第二步:构建高亮的条件
第三步:在获取查询结果时使用三个参数的方法