使用JAVA操作ElasticSearch( Spring Data ElasticSearch)
Spring Data是一个用于简化数据库访问,并支持云服务的开源框架。其主要目标是使得对数据的访问变得方便快捷,并支持map-reduce框架和云计算数据服务。 Spring Data可以极大的简化JPA的写法,可以在几乎不用写实现的情况下,实现对数据的访问和操作。除了CRUD外,还包括如分页、排序等一些常用的功能。
笔者的ElasticSearch集群的版本是6.2.4,导入spring-data-elasticsearch的maven依赖也是3.1.5.RELEASE,不同版本的api可能会有差异
一:准备maven依赖
<!--elasticsearch核心依赖--> <dependency> <groupId>org.elasticsearch</groupId> <artifactId>elasticsearch</artifactId> <version>6.2.4</version> </dependency> <!--elasticsearch客户端--> <dependency> <groupId>org.elasticsearch.client</groupId> <artifactId>transport</artifactId> <version>6.2.4</version> </dependency> <!--日志--> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-to-slf4j</artifactId> <version>2.9.1</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.24</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-simple</artifactId> <version>1.7.21</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.12</version> </dependency> <!--单元测试--> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>compile</scope> </dependency> <!--实体类简化工具--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.16.18</version> </dependency> <!--springframework--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>5.2.3.RELEASE</version> </dependency> <!--spring-data-elasticsearch--> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-elasticsearch</artifactId> <version>3.1.5.RELEASE</version> <exclusions> <exclusion> <groupId>org.elasticsearch.plugin</groupId> <artifactId>transport‐netty4‐client</artifactId> </exclusion> </exclusions> </dependency>
二:创建实体
package com.yjc.entity; import lombok.Data; 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; //lombok相当于get,set,toSting等一系列方法 @Data //代表文档对象(索引库,类型) @Document(indexName = "myindex2",type = "article") public class Article { //文档主键,唯一 @Id //store是否存储(默认false),index是否分词(默认true),type类型 @Field(store = true,index = false,type = FieldType.Integer) private Integer id; //下面配置代表 进行存储并以ik_smart方式分词,(默认开启分词)保持的类型为text,进行查询的时候按照ik_smart方式进行分词 @Field(store = true,analyzer ="ik_smart",searchAnalyzer = "ik_smart",type = FieldType.Text) private String title; //下面配置代表 进行存储并以ik_smart方式分词,保持的类型为text,进行查询的时候按照ik_smart方式进行分词 @Field(store = true,analyzer ="ik_smart",searchAnalyzer = "ik_smart",type = FieldType.Text) private String content; }
三:创建DAO和Service
ArticleDao
package com.yjc.dao; import com.yjc.entity.Article; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.elasticsearch.repository.ElasticsearchRepository; import org.springframework.stereotype.Repository; import java.util.List; @Repository /** * ElasticsearchRepository<要操作的实体类,ID在实体类中类型> * */ public interface ArticleDao extends ElasticsearchRepository<Article,Integer> { //根据标题查询 List<Article> findByTitle(String condition); //根据标题查询(含分页) Page<Article> findByTitle(String condition, Pageable pageable); //根据id List<Article> findById(String condition); }
ArticleService
package com.yjc.service; import com.yjc.entity.Article; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import java.util.List; public interface ArticleService { //添加 void save(Article article); //删除 void delete(Article article); //查询全部 Iterable<Article> findAll(); //分页查询 Page<Article> findAll(Pageable pageable); //根据标题查询 List<Article> findByTitle(String condition); //根据标题查询(含分页) Page<Article> findByTitle(String condition, Pageable pageable); //根据内容搜索并分页 List<Article> findById(String condition); }
ArticleServiceImpl
package com.yjc.service.impl; import com.yjc.dao.ArticleDao; import com.yjc.entity.Article; import com.yjc.service.ArticleService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import java.util.List; @Service public class ArticleServiceImpl implements ArticleService { @Autowired ArticleDao articleDao; @Override public void save(Article article) { articleDao.save(article); } @Override public void delete(Article article) { articleDao.delete(article); } @Override public Iterable<Article> findAll() { return articleDao.findAll(); } @Override public Page<Article> findAll(Pageable pageable) { return articleDao.findAll(pageable); } @Override public List<Article> findByTitle(String condition) { return articleDao.findByTitle(condition); } @Override public Page<Article> findByTitle(String condition, Pageable pageable) { return articleDao.findByTitle(condition,pageable); } @Override public List<Article> findById(String condition) { return articleDao.findById(condition); } }
四:创建Spring的核心配置文件
applicationContext.xml,注意更换命名空间
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:elasticsearch="http://www.springframework.org/schema/data/elasticsearch"
xsi:schemaLocation=" http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/data/elasticsearch
http://www.springframework.org/schema/data/elasticsearch/spring-elasticsearch-1.0.xsd "> <!--创建包扫描器,扫描Dao,自动创建实例--> <elasticsearch:repositories base-package="com.yjc.dao"/> <!--扫描Service--> <context:component-scan base-package="com.yjc.service"/> <!--配置es的连接--> <elasticsearch:transport-client id="client" cluster-nodes="192.168.118.3:9300" cluster-name="elasticsearch"/> <!--es模板对象--> <bean id="elasticsearchTemplate" class="org.springframework.data.elasticsearch.core.ElasticsearchTemplate"> <constructor-arg name="client" ref="client"/> </bean> </beans>
五:测试
package com.yjc.test; import com.yjc.entity.Article; import com.yjc.service.ArticleService; import org.elasticsearch.client.transport.TransportClient; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.data.elasticsearch.core.ElasticsearchTemplate; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import java.util.List; @RunWith(SpringJUnit4ClassRunner.class) //启动单元测试的时候加载的配置文件 @ContextConfiguration(locations = "classpath:applicationContext.xml") public class SpringDataESTest { @Autowired ArticleService articleService; //注入连接对象 @Autowired TransportClient client; //注入模板对象 @Autowired ElasticsearchTemplate elasticsearchTemplate; @Test //创建索引 public void createIndex() { //配置在实体类中已经配置好了,直接创建并添加映射 elasticsearchTemplate.createIndex(Article.class); elasticsearchTemplate.putMapping(Article.class); } @Test //保存文档 public void saveArticle() { Article article = new Article(); article.setId(101); article.setTitle("测试SpringData ElasticSearch"); article.setContent("Spring Data ElasticSearch 基于 spring data API 简化 elasticSearch操 作,将原始操作elasticSearch的客户端API 进行封装 \n" + " Spring Data为Elasticsearch Elasticsearch项目提供集成搜索引擎"); articleService.save(article); } @Test //修改文档 public void update() { Article article = new Article(); article.setId(100); article.setTitle("修改SpringData ElasticSearch"); article.setContent("修改Spring Data ElasticSearch 基于 spring data API 简化 elasticSearch操 作,将原始操作elasticSearch的客户端API 进行封装 \n" + " Spring Data为Elasticsearch Elasticsearch项目提供集成搜索引擎"); articleService.save(article); } @Test //删除文档 public void delete(){ Article article = new Article(); article.setId(100); articleService.delete(article); } @Test //分页查询 public void findAllPage(){ Pageable pageable=PageRequest.of(0,10); Page<Article> all = articleService.findAll(pageable); for (Article article:all.getContent()){ System.out.println(article); } } @Test //带条件查询 public void findByTitle(){ List<Article> articles = articleService.findByTitle("测试"); for (Article article:articles){ System.out.println(article); } } @Test //待条件查询加分页 public void findByTitlePage(){ Pageable pageable=PageRequest.of(0,1); Page<Article> articles = articleService.findByTitle("引擎", pageable); for (Article article:articles.getContent()){ System.out.println(article); } } @Test //根据id进行查询 public void findByContent(){ List<Article> articles = articleService.findById("100"); for (Article article:articles){ System.out.println(article); } } }
Spring Data ElasticSearch中带条件查询是根据Dao层的方法名来判断去哪个域中去搜索数据,常用的命名规范如下
使用elasticsearchTemplate对象将条件进行分词,然后搜索
NativeSearchQueryBuilder builder=new NativeSearchQueryBuilder(); NativeSearchQuery build = builder.withQuery(QueryBuilders.queryStringQuery("人民更改").defaultField("title")).build(); List<Article> articles = elasticsearchTemplate.queryForList(build, Article.class); for (Article article:articles){ System.out.println(article); }