pom文件添加starter如下:
org.springframework.boot
spring-boot-starter-data-elasticsearch
SpringBoot默认支持两种技术和Elasticsearch进行交互:Spring Data Elasticsearch和Jest。
Jest默认不生效,需要导入io.searchbox.client.JestClient。
io.searchbox
jest
5.3.3
Spring Data Elasticsearch主要作用如下:
① ElasticsearchAutoConfiguration中注册了client,属性有clusterNodes和clusterName。
② ElasticsearchDataAutoConfiguration注册了ElasticsearchTemplate来操作ES
@Configuration
@ConditionalOnClass({ Client.class, ElasticsearchTemplate.class })
@AutoConfigureAfter(ElasticsearchAutoConfiguration.class)
public class ElasticsearchDataAutoConfiguration {
@Bean
@ConditionalOnMissingBean
@ConditionalOnBean(Client.class)
public ElasticsearchTemplate elasticsearchTemplate(Client client,
ElasticsearchConverter converter) {
try {
return new ElasticsearchTemplate(client, converter);
}
catch (Exception ex) {
throw new IllegalStateException(ex);
}
}
@Bean
@ConditionalOnMissingBean
public ElasticsearchConverter elasticsearchConverter(
SimpleElasticsearchMappingContext mappingContext) {
return new MappingElasticsearchConverter(mappingContext);
}
@Bean
@ConditionalOnMissingBean
public SimpleElasticsearchMappingContext mappingContext() {
return new SimpleElasticsearchMappingContext();
}
}
③ ElasticsearchRepositoriesAutoConfiguration 启用了ElasticsearchRepository
@Configuration
@ConditionalOnClass({ Client.class, ElasticsearchRepository.class })
@ConditionalOnProperty(prefix = "spring.data.elasticsearch.repositories", name = "enabled", havingValue = "true", matchIfMissing = true)
@ConditionalOnMissingBean(ElasticsearchRepositoryFactoryBean.class)
@Import(ElasticsearchRepositoriesRegistrar.class)
public class ElasticsearchRepositoriesAutoConfiguration {
}
ElasticsearchRepository接口源码如下(类似于JPA中的接口):
@NoRepositoryBean
public interface ElasticsearchRepository extends ElasticsearchCrudRepository {
S index(S var1);
Iterable search(QueryBuilder var1);
Page search(QueryBuilder var1, Pageable var2);
Page search(SearchQuery var1);
Page searchSimilar(T var1, String[] var2, Pageable var3);
void refresh();
Class getEntityClass();
}
application.properties配置如下:
# jest url配置
spring.elasticsearch.jest.uris=http://192.168.2.110:9200
测试类如下:
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringBootJestTest {
@Autowired
JestClient jestClient;
@Test
public void index(){
Article article = new Article();
article.setId(1);
article.setAuthor("Tom");
article.setContent("hello world !");
article.setTitle("今日消息");
//构建一个索引功能,类型为news
Index index = new Index.Builder(article).index("jest").type("news").build();
try {
jestClient.execute(index);
System.out.println("数据索引成功!");
} catch (IOException e) {
e.printStackTrace();
}
}
@Test
public void search(){
//查询表达式
String json = "{\n" +
" \"query\" : {\n" +
" \"match\" : {\n" +
" \"content\" : \"hello\"\n" +
" }\n" +
" }\n" +
"}";
//构建搜索功能
Search search = new Search.Builder(json).addIndex("jest").addType("news").build();
try {
SearchResult result = jestClient.execute(search);
System.out.println(result.getJsonString());
} catch (IOException e) {
e.printStackTrace();
}
}
}
测试存储数据结果如下:
测试查询数据结果如下:
application.properties进行配置:
# Spring data elasticsearch配置
spring.data.elasticsearch.cluster-name=elasticsearch
spring.data.elasticsearch.cluster-nodes=192.168.2.110:9300
启动主程序,可能报错如下(ES版本不合适):
查看Spring Data官网,其中spring data elasticsearch与elasticsearch适配表如下:
官网地址:https://github.com/spring-projects/spring-data-elasticsearch
我们在上篇博文中安装的ES版本为5.6.10,项目中SpringBoot版本为1.5.12,spring-boot-starter-data-elasticsearch为2.1.11,elasticsearch版本为2.4.6。
两种解决办法:① 升级SpringBoot版本;② 安装2.4.6版本的elasticsearch。
这里修改暴露的端口,重新使用docker安装2.4.6版本:
# 拉取2.4.6 镜像
docker pull registry.docker-cn.com/library/elasticsearch:2.4.6
# 启动容器
docker run -e ES_JAVA_OPTS="-Xms256m -Xmx256m" -d -p 9201:9200 -p 9301:9300 --name ES02 bc337c8e4f
application.properties配置文件同步修改:
# jest url配置
spring.elasticsearch.jest.uris=http://192.168.2.110:9201
# Spring data elasticsearch配置
spring.data.elasticsearch.cluster-name=elasticsearch
spring.data.elasticsearch.cluster-nodes=192.168.2.110:9301
此时再次启动程序:
类似于JPA,编写自定义Repository接口,继承自ElasticsearchRepository:
public interface BookRepository extends ElasticsearchRepository {
public List findByBookNameLike(String bookName);
}
这里第一个参数为对象类型,第二个参数为对象的主键类型。
BookRepository 所拥有的方法如下图:
Book源码如下:
// 这里注意注解
@Document(indexName = "elastic",type = "book")
public class Book {
private Integer id;
private String bookName;
private String author;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getBookName() {
return bookName;
}
public void setBookName(String bookName) {
this.bookName = bookName;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
@Override
public String toString() {
return "Book{" +
"id=" + id +
", bookName='" + bookName + '\'' +
", author='" + author + '\'' +
'}';
}
}
测试类如下:
@Autowired
BookRepository bookRepository;
@Test
public void testRepository(){
Book book = new Book();
book.setAuthor("吴承恩");
book.setBookName("西游记");
book.setId(1);
bookRepository.index(book);
System.out.println("BookRepository 存入数据成功!");
}
测试结果如下图:
测试获取示例如下:
@Test
public void testRepository2(){
for (Book book : bookRepository.findByBookNameLike("游")) {
System.out.println("获取的book : "+book);
} ;
Book book = bookRepository.findOne(1);
System.out.println("根据id查询 : "+book);
}
测试结果如下图:
Elasticsearch支持方法关键字如下图所示
即,在BookRepository中使用上述关键字构造方法,即可使用,Elastic自行实现其功能!
支持@Query注解
如下所示,直接在方法上使用注解:
public interface BookRepository extends ElasticsearchRepository {
@Query("{"bool" : {"must" : {"field" : {"name" : "?0"}}}}")
Page findByName(String name,Pageable pageable);
}
存入数据源码示例如下:
@Autowired
ElasticsearchTemplate elasticsearchTemplate;
@Test
public void testTemplate01(){
Book book = new Book();
book.setAuthor("曹雪芹");
book.setBookName("红楼梦");
book.setId(2);
IndexQuery indexQuery = new IndexQueryBuilder().withId(String.valueOf(book.getId())).withObject(book).build();
elasticsearchTemplate.index(indexQuery);
}
测试结果如下:
查询数据示例如下:
@Test
public void testTemplate02(){
QueryStringQueryBuilder stringQueryBuilder = new QueryStringQueryBuilder("楼");
stringQueryBuilder.field("bookName");
SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(stringQueryBuilder).build();
Page books = elasticsearchTemplate.queryForPage(searchQuery,Book.class);
Iterator iterator = books.iterator();
while(iterator.hasNext()){
Book book = iterator.next();
System.out.println("该次获取的book:"+book);
}
}
测试结果如下: