Spring Data 整合 ElasticSearch

Spring Data ElasticSearch简介

1 什么是Spring Data

Spring Data是一个用于简化持久层数据访问的开源框架。其主要目标是使得对数据的访问变得方便快捷。 Spring Data可以极大的简化数据操作的写法,可以在几乎不用写实现的情况下,实现对数据的访问和操作。包括CRUD外,还包括如分页、排序等一些常用的功能,几乎可以节省持久层代码80%以上的编码工作量。

Spring Data的官网

2 什么是Spring Data ElasticSearch

Spring Data ElasticSearch 基于 spring data API 简化 elasticSearch操作,将原始操作elasticSearch的客户端API 进行封装 。Spring Data为Elasticsearch项目提供集成搜索引擎。Spring Data Elasticsearch POJO的关键功能区域为中心的模型与Elastichsearch交互文档和轻松地编写一个存储库数据访问层。

官方网站

用来操作ElasticSearch的框架,使得开发更加便捷

环境搭建

实现步骤:

  1. 创建SpringBoot的项目
  2. 勾选starter依赖坐标
  3. 编写持久层接口GoodDao,编写pojo实体类
  4. 配置文件,集群配置,ElasticSearch服务地址http://127.0.0.1:9300

实现过程:

  1. 创建SpringBoot的项目

  2. 勾选starter依赖坐标
    在这里插入图片描述

  3. 编写持久层接口GoodDao,编写pojo实体类

    public interface GoodDao {
    }
    

    pojo实体类,商品good

/**
 * indexName  设置索引库名称
 * type  设置类型的名称
 * shards  设置分片数,默认是5
 * replicas 设置副本数,默认是1
 */
@Data
@Builder
@Document(indexName = "springdataelastic",type = "goods",shards = 5,replicas = 1)
public class Goods {
    @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;//图片地址
    //getter,setter,toString
}
  1. 配置文件,集群配置,ElasticSearch服务地址http://127.0.0.1:9300
#配置集群的名称
spring.data.elasticsearch.cluster-name=elasticsearch
#配置集群的服务地址
spring.data.elasticsearch.cluster-nodes=127.0.0.1:9300

常用操作

1、创建索引库操作

几个用到的注解:

  • @Document:声明索引库配置
    • indexName:索引库名称
    • type:类型名称,默认是“docs”
    • shards:分片数量,默认5
    • replicas:副本数量,默认1
  • @Id:声明实体类的id
  • @Field:声明字段属性
    • type:字段的数据类型
    • analyzer:指定分词器类型
    • index:是否创建索引默认为true
    • store:是否存储 默认为false

实体类配置:

/**
 * 商品实体类
 * @Document() 注解作用:定义一个索引库,一个类型
 * indexName属性:指定索引库的名称
 * type属性:指定类型名称
 * shards属性:指定分片数
 * replicas属性:指定复制副本数
 */
@Document(indexName = "ahu4",type = "goods",shards = 5,replicas = 1)
public class Good {
    //必须有id,这里的id是全局唯一的标识,等同于es中的“_id”
    @Id
    private Long id;
    /**
     * type: 字段数据类型
     * analyzer: 分词器类型
     * index: 是否索引(默认值:true)
     * store: 是否存储(默认值:false)
     */
    @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;//图片地址
	//getter ,setter ,toString
}

测试类:

/**
 * 目标:完成创建索引,配置映射
 * 1.注入ElasticSearchTemplate对象
 * 2.配置Good实体类
 * 3.调用创建索引的方法createIndex()
 *   调用配置映射的方法PutMapping()
 *   测试删除索引方法deleteIndex()
 */
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringdataEsIndex {

    //注入ElasticSearchTemplate模板对象
    @Autowired
    private ElasticsearchTemplate elasticsearchTemplate;
    //创建索引,配置映射
    @Test
    public void createIndexAndPutMapping() {
        //创建索引
        boolean indexResult = elasticsearchTemplate.createIndex(Good.class);
        System.out.println("创建索引结果:"+indexResult);
        //创建配置映射
        elasticsearchTemplate.putMapping(Good.class);
        System.out.println("配置映射结果:"+indexResult);
    }
    //删除索引
    @Test
    public void deleteIndex(){
        elasticsearchTemplate.deleteIndex(Good.class);
    }
}

创建结果
在这里插入图片描述

2、文档的常见增删改查

继承ElasticsearchRespository模板接口

/**
 *  继承持久层接口的ElasticSearch的模板接口
 */
public interface GoodDao extends ElasticsearchRepository<Good,Long> {
    
}

测试类代码:

/**
 * 新增、修改、删除、根据id查询、查询所有、分页查询
 * 步骤:
 * 1.dao层接口继承ElasticSearchRepository的模板接口
 * 2.编写业务层的所有方法
 * 3.测试所有方法
 */
@RunWith(SpringRunner.class)
@SpringBootTest
public class Demo02DocCURD {
	@Autowired
	private GoodsDao goodsDao;

	//插入文档
	@Test
	public void save() {
		Goods good = Goods.builder().id(1L).title("小米手机").brand("小米").price(19999.0).build();
		goodsDao.save(good);
	}

	//批量新增
	@Test
	public void saveAll() {
		ArrayList<Goods> goods = new ArrayList<>();
		for (int i = 0; i < 10; i++) {
			Goods good = Goods.builder().id((long) i).title("小米手机").brand("小米").price((double) i).build();
			goods.add(good);
		}
		goodsDao.saveAll(goods);
	}

	//修改文档
	@Test
	public void update() {
		Goods good = Goods.builder().id(1L).title("小米手机").brand("小米").price(19999.0).images("http://baidu.com/12479122.jpg").build();
		goodsDao.save(good);
	}

	//删除文档
	@Test
	public void delete() {
		Goods good = Goods.builder().id(1L).build();
		goodsDao.delete(good);
	}

	//批量删除
	@Test
	public void deleteAll() {
		goodsDao.deleteAll();
	}

	//根据id查询
	//Optional是对所有pojo的封装对象
	//jackson的反序列化需要使用无参构造函数,添加一个无参构造函数就可以了
	@Test
	public void findById() {
		Optional<Goods> goods = goodsDao.findById(2L);
		Goods goods1 = goods.get();
		System.out.println(goods1);
	}

	//查询所有
	@Test
	public void findAll(){
		Iterable<Goods> goods = goodsDao.findAll();
		for (Goods good : goods) {
			System.out.println(good);
		}
	}

	//分页查询
	@Test
	public void findByPage(){
		//设置排序
		Sort sort = new Sort(Sort.Direction.DESC,"id");
		int currentPage = 2;
		int pageSize = 3;
		//设置分页查询
		PageRequest pageRequest = PageRequest.of(currentPage, pageSize, sort);
		//分页查询
		Page<Goods> goodsPage = goodsDao.findAll(pageRequest);
		for (Goods goods : goodsPage.getContent()) {
			System.out.println(goods);
		}
	}
}

3、Search查询

ElasticSearch的search方法中QueryBuilders,就是原始API查询对象构建对象QueryBuilders。QueryBuilders具备的能力,search方法都具备。

/**
 * 目标:搜索
 * term查询、match查询,match_all查询...
 */
@RunWith(SpringRunner.class)
@SpringBootTest
public class Demo03Search {
	@Autowired
	private GoodsDao goodsDao;

	//term查询
	@Test
	public void term() {
		Iterable<Goods> goods = goodsDao.search(QueryBuilders.termQuery("title", "小米"));
		for (Goods good : goods) {
			System.out.println(good);
		}
	}

	//terms查询
	@Test
	public void terms() {
		Iterable<Goods> goods = goodsDao.search(QueryBuilders.termsQuery("title", "小米","手机"));
		for (Goods good : goods) {
			System.out.println(good);
		}
	}

	//multimatch查询
	@Test
	public void multiMatch() {
		Iterable<Goods> goods = goodsDao.search(QueryBuilders.multiMatchQuery("苹果", "title","brand"));
		for (Goods good : goods) {
			System.out.println(good);
		}
	}

	//match查询
	@Test
	public void match() {
		Iterable<Goods> goods = goodsDao.search(QueryBuilders.matchQuery("title", "苹果"));
		for (Goods good : goods) {
			System.out.println(good);
		}
	}

	//match精确查询
	@Test
	public void matchExaxt() {
		Iterable<Goods> goods = goodsDao.search(QueryBuilders.matchQuery("title", "苹果手机").operator(Operator.AND));
		for (Goods good : goods) {
			System.out.println(good);
		}
	}

	//matchAll查询
	@Test
	public void matchAll() {
		Iterable<Goods> goods = goodsDao.search(QueryBuilders.matchAllQuery());
		for (Goods good : goods) {
			System.out.println(good);
		}
	}

	//分页和排序
	@Test
	public void pageAndSort() {
		//设置排序
		Sort sort = new Sort(Sort.Direction.DESC,"id");
		int currentPage = 2;
		int pageSize = 3;
		//设置分页查询
		PageRequest pageRequest = PageRequest.of(currentPage, pageSize, sort);
		//分页查询
		Page<Goods> goodsPage = goodsDao.findAll(pageRequest);
		for (Goods goods : goodsPage.getContent()) {
			System.out.println(goods);
		}
	}

	//布尔查询
	@Test
	public void boolQuery() {
		BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
		boolQueryBuilder.must(QueryBuilders.matchQuery("title","小米"));
		boolQueryBuilder.mustNot(QueryBuilders.matchQuery("title","电视"));
		boolQueryBuilder.should(QueryBuilders.matchQuery("title","手机"));
		Iterable<Goods> goods = goodsDao.search(boolQueryBuilder);
		for (Goods good : goods) {
			System.out.println(good);
		}
	}

	//范围查询
	@Test
	public void rangeQuery() {
		RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("price");
		rangeQueryBuilder.lt(5000);
		rangeQueryBuilder.gt(2000);
		Iterable<Goods> goods = goodsDao.search(rangeQueryBuilder);
		for (Goods good : goods) {
			System.out.println(good);
		}
	}

	//模糊查询
	@Test
	public void fuzzyQuery() {
		FuzzyQueryBuilder fuzzyQueryBuilder = QueryBuilders.fuzzyQuery("title", "appla手机");
		Iterable<Goods> goods = goodsDao.search(fuzzyQueryBuilder);
		for (Goods good : goods) {
			System.out.println(good);
		}
	}
}

4、自定义方法名称查询

GoodsRepository提供了非常强大的自定义查询功能;只要遵循SpringData提供的语法,我们可以任意定义方法声明;

查询语法:findBy+字段名+Keyword+字段名+…

KeywordSampleElasticsearch Query String
AndfindByNameAndPrice{"bool" : {"must" : [ {"field" : {"name" : "?"}}, {"field" : {"price" : "?"}} ]}}
OrfindByNameOrPrice{"bool" : {"should" : [ {"field" : {"name" : "?"}}, {"field" : {"price" : "?"}} ]}}
IsfindByName{"bool" : {"must" : {"field" : {"name" : "?"}}}}
NotfindByNameNot{"bool" : {"must_not" : {"field" : {"name" : "?"}}}}
BetweenfindByPriceBetween{"bool" : {"must" : {"range" : {"price" : {"from" : ?,"to" : ?,"include_lower" : true,"include_upper" : true}}}}}
BeforefindByPriceBefore{"bool" : {"must" : {"range" : {"price" : {"from" : null,"to" : ?,"include_lower" : true,"include_upper" : true}}}}}
AfterfindByPriceAfter{"bool" : {"must" : {"range" : {"price" : {"from" : ?,"to" : null,"include_lower" : true,"include_upper" : true}}}}}
LikefindByNameLike{"bool" : {"must" : {"field" : {"name" : {"query" : "?*","analyze_wildcard" : true}}}}}
StartingWithfindByNameStartingWith{"bool" : {"must" : {"field" : {"name" : {"query" : "?*","analyze_wildcard" : true}}}}}
EndingWithfindByNameEndingWith{"bool" : {"must" : {"field" : {"name" : {"query" : "*?","analyze_wildcard" : true}}}}}
InfindByNameIn(Collection<String>names){"bool" : {"must" : {"bool" : {"should" : [ {"field" : {"name" : "?"}}, {"field" : {"name" : "?"}} ]}}}}
NotInfindByNameNotIn(Collection<String>names){"bool" : {"must_not" : {"bool" : {"should" : {"field" : {"name" : "?"}}}}}}
OrderByfindByNameOrderByNameDesc{"sort" : [{ "name" : {"order" : "desc"} }],"bool" : {"must" : {"field" : {"name" : "?"}}}

持久层接口:

/**
 *  ElasticsearchRepository 持久层操作ElasticSearch的模板接口
 */
public interface GoodsDao extends ElasticsearchRepository<Goods, Long> {
    //根据商品的标题和加个查询所有的商品信息
    List<Goods> findAllByTitleAndPrice(String title, Double price);
}

测试类:

@RunWith(SpringRunner.class)
@SpringBootTest
public class Demo04CustomMethodNameQuery {
	@Autowired
	private GoodsDao goodsDao;

	@Test
	public void findAllByTitleAndPrice(){
		List<Goods> goods = goodsDao.findAllByTitleAndPrice("小米", 8.0);
		for (Goods good : goods) {
			System.out.println(good);
		}
	}
}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值