什么是SpringData
Spring Data是一个用于简化数据库访问,并支持云服务的开源框架。其主要目标是使得对数据的访问变得方便快
捷,并支持map-reduce框架和云计算数据服务。 Spring Data可以极大的简化JPA的写法,可以在几乎不用写实现
的情况下,实现对数据的访问和操作。除了CRUD外,还包括如分页、排序等一些常用的功能。
Spring Data的官网:http://projects.spring.io/spring-data/
什么是SpringDataElasticSearch
Spring Data ElasticSearch 基于 spring data API 简化 elasticSearch操作,将原始操作elasticSearch的客户端API
进行封装 。Spring Data为Elasticsearch项目提供集成搜索引擎。Spring Data Elasticsearch POJO的关键功能区域
为中心的模型与Elastichsearch交互文档和轻松地编写一个存储库数据访问层。
官方网站:http://projects.spring.io/spring-data-elasticsearch/
创建工程并且实现使用SpringDataElasticSearch创建索引和文档
第一步:创建一个maven工程,导入依赖
<dependency> <groupId>org.elasticsearch</groupId> <artifactId>elasticsearch</artifactId> <version>5.6.8</version> </dependency> <dependency> <groupId>org.elasticsearch.client</groupId> <artifactId>transport</artifactId> <version>5.6.8</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> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>2.8.1</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.8.1</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-annotations</artifactId> <version>2.8.1</version> </dependency> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-elasticsearch</artifactId> <version>3.0.5.RELEASE</version> <exclusions> <exclusion> <groupId>org.elasticsearch.plugin</groupId> <artifactId>transport‐netty4‐client</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>5.0.4.RELEASE</version> </dependency>
第二步:创建实体Article
基于spring data elasticsearch注解配置索引、映射和实体的
package com.wish.entity; 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; //@Document 文档对象 (索引信息、文档类型) @Document(indexName = "blog3",type = "table03") public class Article { /* @Document(indexName="blob3",type="article"): indexName:索引的名称(必填项) type:索引的类型 @Id:主键的唯一标识 @Field(index=true,analyzer="ik_smart",store=true,searchAnalyzer="ik_smart",type=FieldType.text) 每个文档的字段配置(类型、是否分词、是否存储、分词器 ) index:是否设置分词 analyzer:存储时使用的分词器 searchAnalyze:搜索时使用的分词器 store:是否存储 type: 数据类型 */ @Id @Field(store = true,index = false,type = FieldType.Integer) private Integer id; @Field(index = true,analyzer = "ik_smart",store = true,searchAnalyzer = "ik_smart",type = FieldType.text) private String title; @Field(index = true,analyzer = "ik_smart",store = true,searchAnalyzer = "ik_smart",type = FieldType.text) private String content; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } @Override public String toString() { return "Table01{" + "id=" + id + ", title='" + title + '\'' + ", content='" + content + '\'' + '}'; } }
第三步:编写dao层
package com.wish.dao; import com.wish.entity.Article; import org.springframework.data.elasticsearch.repository.ElasticsearchRepository; public interface ArticleRepository extends ElasticsearchRepository<Article, Integer> { }
第三步:编写service
package com.wish.service; import com.wish.entity.Article; public interface ArticleService { public void save(Article article); }
第四步:编写service的实现类
package com.wish.service.impl; import com.wish.dao.ArticleRepository; import com.wish.entity.Article; import com.wish.service.ArticleService; import org.springframework.beans.factory.annotation.Autowired;
@Service public class ArticleServiceImpl implements ArticleService { @Autowired private ArticleRepository articleRepository; @Override public void save(Article article) { articleRepository.save(article); } }
第五步:配置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.wish.dao"/> <!--扫描service包,创建service的实体--> <context:component-scan base-package="com.wish.service"/> <!--配置 ElasticSearch模的连接--> <elasticsearch:transport-client id="client" cluster-nodes="127.0.0.1:9300" cluster-name="my-elasticsearch"/> <!-- ElasticSearch模模板对象--> <bean id="elasticsearchTemplate" class="org.springframework.data.elasticsearch.core.ElasticsearchTemplate"> <constructor-arg name="client" ref="client"></constructor-arg> </bean> </beans>
第六步:创建测试类SpringDataESTest
package com.wish; import com.wish.entity.Article; import com.wish.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.elasticsearch.core.ElasticsearchTemplate; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "classpath:applicationContext.xml") public class SpringDataESTest { @Autowired private ArticleService articleService; @Autowired private TransportClient client; @Autowired private ElasticsearchTemplate elasticsearchTemplate; /** * 创建索引和映射 */ @Test public void createIndex() { elasticsearchTemplate.createIndex(Article.class); elasticsearchTemplate.putMapping(Article.class); } /** * 测试保存文档 */ @Test public void saveArticle() { Article article = new Article(); article.setId(100); article.setTitle("测试SpringData ElasticSearch"); article.setContent("Spring Data ElasticSearch 基于 spring data API 简化 elasticSearch操\n" + " 作,将原始操作elasticSearch的客户端API 进行封装\n" + " Spring Data为Elasticsearch Elasticsearch项目提供集成搜索引擎"); articleService.save(article); } }
创建索引和映射的效果和遇到错误
注意:如果创建时报一下错误
1.org.springframework.data.elasticsearch.repository.support.AbstractElasticsearchRepository - failed to load elasticsearch nodes : org.elasticsearch.client.transport.NoNodeAvailableException: None of the configured nodes are available: [{#transport#-1}{-jhPfiM0Sh6cKPV4rCAKlg}{localhost}{127.0.0.1:9300}]
解决:(1)删除掉data文件夹,进行重启(2)注意配置文件中的cluster‐name的值与图片中红圈的一样
2.org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'com.wish.SpringDataESTest': Unsatisfied dependency expressed through field 'articleService'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.wish.service.ArticleService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
解决:这个错是因为一开写着急了,service的实现类没有用@service注解标识
创建文档的效果
SpringDataElasticSearch的常用操作
增删改查方法测试
修改service和service实现类
package com.wish.service; import com.wish.entity.Article; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; public interface ArticleService { //保存 public void save(Article article); //删除 public void delete(Article article); //查询全部 public Iterable<Article> findAll(); //分页查询 public Page<Article> findAll(Pageable pageable); }
package com.wish.service.impl; import com.wish.dao.ArticleRepository; import com.wish.entity.Article; import com.wish.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; @Service public class ArticleServiceImpl implements ArticleService { @Autowired private ArticleRepository articleRepository; @Override public void save(Article article) { articleRepository.save(article); } @Override public void delete(Article article) { articleRepository.delete(article); } @Override public Iterable<Article> findAll() { Iterable<Article> iter = articleRepository.findAll(); return iter; } @Override public Page<Article> findAll(Pageable pageable) { return articleRepository.findAll(pageable); } }
增加文档
/**测试保存*/ @Test public void save(){ Article article = new Article(); article.setId(1001); article.setTitle("elasticSearch 3.0版本发布"); article.setContent("ElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的\n" + " 全文搜索引擎,基于RESTful web接口"); articleService.save(article); }
效果
修改文档
/**测试更新*/ @Test public void update(){ Article article = new Article(); article.setId(1001); article.setTitle("[更新]elasticSearch 3.0版本发布"); article.setContent("[更新]ElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的\n" + " 全文搜索引擎,基于RESTful web接口"); articleService.save(article); }
效果
删除文档
/**测试删除*/ @Test public void delete(){ Article article = new Article(); article.setId(1001); articleService.delete(article); }
效果
批量添加文档
/**批量插入*/ @Test public void save100(){ for(int i=1;i<=20;i++){ Article article = new Article(); article.setId(i); article.setTitle(i+"elasticSearch 3.0版本发布..,更新"); article.setContent(i+"ElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用\n" + " 户能力的全文搜索引擎,基于RESTful web接口"); articleService.save(article); } }
效果
分页查询文档
/**分页查询*/ @Test public void findAllPage() { Pageable pageable = PageRequest.of(1, 10); Page<Article> page = articleService.findAll(pageable); for (Article article : page.getContent()) { System.out.println(article); } }
效果
常用查询命名规则
带条件查询方法测试
修改dao层
package com.wish.dao; import com.wish.entity.Article; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.elasticsearch.repository.ElasticsearchRepository; import java.util.List; public interface ArticleRepository extends ElasticsearchRepository<Article, Integer> { //根据标题查询 List<Article> findByTitle(String condition); //根据标题查询(含分页) Page<Article> findByTitle(String condition, Pageable pageable); }
修改service层和service的实现层
package com.wish.service; import com.wish.entity.Article; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import java.util.List; public interface ArticleService { //保存 public void save(Article article); //删除 public void delete(Article article); //查询全部 public Iterable<Article> findAll(); //分页查询 public Page<Article> findAll(Pageable pageable); //根据标题查询 List<Article> findByTitle(String condition); //根据标题查询(含分页) Page<Article> findByTitle(String condition, Pageable pageable); }
package com.wish.service.impl; import com.wish.dao.ArticleRepository; import com.wish.entity.Article; import com.wish.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 private ArticleRepository articleRepository; @Override public void save(Article article) { articleRepository.save(article); } @Override public void delete(Article article) { articleRepository.delete(article); } @Override public Iterable<Article> findAll() { Iterable<Article> iter = articleRepository.findAll(); return iter; } @Override public Page<Article> findAll(Pageable pageable) { return articleRepository.findAll(pageable); } @Override public List<Article> findByTitle(String condition) { return articleRepository.findByTitle(condition); } @Override public Page<Article> findByTitle(String condition, Pageable pageable) { return articleRepository.findByTitle(condition,pageable); } }
带条件查询
/**条件查询*/ @Test public void findByTitle(){ String condition = "版本"; List<Article> articleList = articleService.findByTitle(condition); for(Article article:articleList){ System.out.println(article); } }
效果
带条件分页查询
/**条件分页查询*/ @Test public void findByTitlePage(){ String condition = "版本"; Pageable pageable = PageRequest.of(2,5); Page<Article> page = articleService.findByTitle(condition,pageable); int count=0; for(Article article:page.getContent()){ count++; System.out.println(article); } System.out.println("总记录数:"+count); }
效果
使用Elasticsearch的原生查询对象进行查询
@Test public void findByNativeQuery() { //创建一个SearchQuery对象 SearchQuery searchQuery = new NativeSearchQueryBuilder() //设置查询条件,此处可以使用QueryBuilders创建多种查询 .withQuery(QueryBuilders.queryStringQuery("版本").defaultField("title")) //还可以设置分页信息 .withPageable(PageRequest.of(1, 5)) //创建SearchQuery对象 .build(); //使用模板对象执行查询 elasticsearchTemplate.queryForList(searchQuery, Article.class).forEach(article -> System.out.println(article)); }
效果