Spring Data 整合 ElasticSearch搜索服务器
一、基于 maven 导入坐标(pom.xml文件)
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.linuxidc.maven</groupId>
<artifactId>elasticsearch_springdata</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>elasticsearch_springdata</name>
<dependencies>
<!-- Spring data elasticsearch 对 elasticsearch api 简化封装 -->
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>2.4.0</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-elasticsearch</artifactId>
<version>2.0.4.RELEASE</version>
</dependency>
<!-- 导入 spring-test 和 junit 编写测试用例 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.2.8.RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<!-- Slf4j-log4j 日志包 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.12</version>
</dependency>
</dependencies>
</project>
二、在 src/main/resources 下建立 applicationContext.xml 和 log4j.properties
引入 spring data elasticsearch 名称空间
<?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.linuxidc.dao" />
<!-- 扫描Service包 -->
<context:component-scan base-package="com.linuxidc.service" />
<!-- 配置elasticsearch 连接 -->
<elasticsearch:transport-client id="client" cluster-nodes="localhost:9300" />
<!-- spring data elasticsearch DAO 必须依赖 elasticsearchTemplate -->
<bean id="elasticsearchTemplate"
class="org.springframework.data.elasticsearch.core.ElasticsearchTemplate">
<constructor-arg name="client" ref="client" />
</bean>
</beans>
三、在domain中编写测试用的实体类
索引和映射如何创建 --- 基于 spring data elasticsearch 注解
在使用 spring data elasticsearch 开发, 需要将索引和映射信息 配置实体类上面
@Document 文档对象 (索引信息、文档类型 )
@Id 文档主键 唯一标识
@Field 每个文档的字段配置(类型、是否分词、是否存储、分词器 )
package com.linuxidc.domain;
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.FieldIndex;
import org.springframework.data.elasticsearch.annotations.FieldType;
/**
* 文档实体类
*
* @author linuxidc
* @version 1.0,2017-11-15 14:53
*/
@Document(indexName = "blog3", type = "article")
public class Article {
/** ID */
@Id
@Field(index = FieldIndex.not_analyzed, store = true, type = FieldType.Integer)
private Integer id;
/** 文档标题 */
@Field(index = FieldIndex.analyzed, analyzer = "ik", store = true, searchAnalyzer = "ik", type = FieldType.String)
private String title;
/** 文档内容 */
@Field(index = FieldIndex.analyzed, analyzer = "ik", store = true, searchAnalyzer = "ik", type = FieldType.String)
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 "Article{" + "id=" + id + ", title='" + title + '\'' + ", content='" + content + '\'' + '}';
}
}
四、编写 DAO接口
第二个方法里,
分页条件查询,只需要在查询方法中,添加 Pageable 对象
排序条件查询,只需要在查询方法中,添加 Sort 对象
package com.linuxidc.dao;
import java.util.List;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import com.linuxidc.domain.Article;
/**
* 文档的DAO层接口
*
* @author linuxidc
* @version 1.0,2017-11-15 15:02
*/
public interface ArticleRepository extends ElasticsearchRepository<Article, Integer> {
/**
* 根据标题查找文档
*
* @param title 文档标题
* @return 文档集合
*/
List<Article> findByTitle(String title);
/**
* 根据标题查找文档分页数据
*
* @param title 文档标题
* @param pageable 分页对象
* @return 文档的分页数据
*/
Page<Article> findByTitle(String title, Pageable pageable);
}
五、编写 Service接口和实现类
Spring data Search CRUD 操作
CurdRepository 提供增删改查 save、delete、findAll 、findOne
PagingAndSortingRepository 提供分页和排序
package com.linuxidc.service;
import java.util.List;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import com.linuxidc.domain.Article;
/**
* 文档的Service层接口
*
* @author linuxidc
* @version 1.0,2017-11-15 15:09
*/
public interface ArticleService {
/**
* 文档保存的方法
*
* @param article 文档对象
*/
void save(Article article);
/**
* 文档删除的方法
*
* @param article 文档对象
*/
void delete(Article article);
/**
* 根据id查找文档的方法
*
* @param id 文档id
* @return 查找到的文档对象
*/
Article findOne(Integer id);
/**
* 查找所有的文档
*
* @return 文档的迭代器
*/
Iterable<Article> findAll();
/**
* 分页显示所有文档
*
* @param pageable 分页对象
* @return 文档的分页数据
*/
Page<Article> findAll(Pageable pageable);
/**
* 根据标题查找文档
*
* @param title 文档标题
* @return 文档集合
*/
List<Article> findByTitle(String title);
/**
* 根据标题查找文档分页数据
*
* @param title 文档标题
* @param pageable 分页对象
* @return 文档的分页数据
*/
Page<Article> findByTitle(String title, Pageable pageable);
}
package com.linuxidc.service.impl;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import com.linuxidc.dao.ArticleRepository;
import com.linuxidc.domain.Article;
import com.linuxidc.service.CustomerService;
/**
* 文档的Service层实现类
*
* @author linuxidc
* @version 1.0,2017-11-15 15:21
*/
@Service
public class ArticleServiceImpl implements ArticleService {
@Autowired
private ArticleRepository articleRepository;
@Override
void save(Article article) {
articleRepository.save(article);
}
@Override
void delete(Article article) {
articleRepository.delete(article);
}
@Override
Article findOne(Integer id) {
return articleRepository.findOne(id);
}
@Override
Iterable<Article> findAll() {
return articleRepository.findAll(new Sort(new Sort.Order(Sort.Direction.ASC, "id")));
}
@Override
Page<Article> findAll(Pageable pageable) {
return articleRepository.findAll(pageable);
}
@Override
List<Article> findByTitle(String title) {
return articleRepository.findByTitle(title);
}
@Override
Page<Article> findByTitle(String title, Pageable pageable) {
return articleRepository.findByTitle(title, pageable);
}
}
六、测试代码
package com.linuxidc.service.impl;
import org.elasticsearch.client.Client;
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 com.linuxidc.domain.Article;
import com.linuxidc.service.ArticleService;
/**
* 文档的service测试类
*
* @author linuxidc
* @version 1.0,2017-11-15 15:40
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class ArticleServiceTest {
/** 注入service */
@Autowired
private ArticleService articleService;
/** 注入客户端对象 基于原生API */
@Autowired
private Client client;
/** 注入es服务器模板 */
@Autowired
private ElasticsearchTemplate elasticsearchTemplate;
/**
* 通过 ElasticsearchTemplate 创建索引和添加映射
*/
@Test
public void createIndex() {
elasticsearchTemplate.createIndex(Article.class);
elasticsearchTemplate.putMapping(Article.class);
}
/**
* 添加方法测试
*/
@Test
public void testSave() {
Article article = new Article();
article.setId(1001);
article.setTitle("Spring Data Elasticsearch 1.3.1 昨天发布");
article.setContent(
"DATAES-171 - 添加失效查询关键字支持 DATAES-194 - 测试可以清理 data 目录 DATAES-179 - 支持 Attachment 字段类型 DATAES-94 - "
+ "更新到最新版本的 elasticsearch 1.7.3 驱动器");
articleService.save(article);
}
/**
* 根据索引删除的方法测试
*/
@Test
public void testDelete() {
Article article = new Article();
article.setId(1001);
articleService.delete(article);
}
/**
* 根据索引查询的方法测试
*/
@Test
public void testFindOne() {
System.out.println(articleService.findOne(1001));
}
/**
* 添加100条测试数据的方法
*/
@Test
public void testSaveBatch() {
for (int i = 1; i <= 100; i++) {
Article article = new Article();
article.setId(i);
article.setTitle(i + "Spring Data Elasticsearch 1.3.1 昨天发布");
article.setContent(
i + "DATAES-171 - 添加失效查询关键字支持 DATAES-194 - 测试可以清理 data 目录 DATAES-179 - 支持 Attachment 字段类型 DATAES-94 -"
+ " 更新到最新版本的 elasticsearch 1.7.3 驱动器");
articleService.save(article);
}
}
/**
* 排序分页查询的方法测试
*/
@Test
public void testSortAndPaging() {
Iterable<Article> articles = articleService.findAll();
for (Article article : articles) {
System.out.println(article);
}
Pageable pageable = new PageRequest(0, 10);
Page<Article> pageData = articleService.findAll(pageable);
for (Article article : pageData.getContent()) {
System.out.println(article);
}
}
/**
* 条件查询的方法测试
*/
@Test
public void testConditionQuery() {
// 查询 标题中含有 “昨天”
// List<Article> articles = articleService.findByTitle("昨天");
// for (Article article : articles) {
// System.out.println(article);
// }
// 查询 标题中含有 “昨天” 1-10条
Pageable pageable = new PageRequest(0, 10);
Page<Article> pageData = articleService.findByTitle("昨天", pageable);
System.out.println("总记录数:" + pageData.getTotalElements());
for (Article article : pageData.getContent()) {
System.out.println(article);
}
}
}
Elasticsearch 教程系列文章: