Elasticsearch Java API有四类client连接方式
- TransportClient
- RestClient
- Jest
- Spring Data Elasticsearch
其中TransportClient和RestClient是Elasticsearch原生的api。TransportClient可以支持2.x,5.x版本,TransportClient将会在Elasticsearch 7.0弃用并在8.0中完成删除,替而代之,我们使用Java High Level REST Client,它使用HTTP请求而不是Java序列化请求。
Jest是Java社区开发的,是Elasticsearch的Java Http Rest客户端;Spring Data Elasticsearch是spring集成的Elasticsearch开发包。
建议:TransportClient将会在后面的版本中弃用,因此不推荐后续使用;而Jest由于是社区维护,所以更新有一定延迟,目前最新版对接ES6.3.1,近一个月只有四个issue,说明整体活跃度较低,因此也不推荐使用;Spring Data Elasticsearch主要是与Spring生态对接,可以在web系统中整合到Spring中使用。目前比较推荐使用官方的高阶、低阶Rest Client,官方维护,比较值得信赖。本文主要介绍RestClient,其他的只做简单概述。
TransportClient操作
在pom中引入es的包。
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<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>junit</groupId>
<artifactId>junit</artifactId>
<version>RELEASE</version>
<!--<scope>test</scope>-->
</dependency>
</dependencies>
然后可以开发了。
spring data ElasticSearch操作。
1、在pom中导入spring以及Spring Data Elasticsearch依赖。
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<spring.version>5.0.2.RELEASE</spring.version>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>RELEASE</version>
<!--<scope>test</scope>-->
</dependency>
<!--transportClient需要的-->
<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>
<!--springDataElasticSearch需要的-->
<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-netty-client</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- provide by spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>1.2.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.0.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.0.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.7.1</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.25</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>5.0.2.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.0.4.RELEASE</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>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>
<!-- provide by spring end -->
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-servlet_3.0_spec</artifactId>
<version>1.0</version>
<scope>test</scope>
</dependency>
</dependencies>
2、创建applicationContext.xml并配置es相关参数(client、dao接口包扫描、es模板Template)。
<?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 ">
<!-- 配置elasticsearch 连接 client -->
<elasticsearch:transport-client id="esClient" cluster-name="my-elasticsearch" cluster-nodes="127.0.0.1:9301,127.0.0.1:9302,127.0.0.1:9303" />
<!-- 配置扫描DAO接口包 -->
<elasticsearch:repositories base-package="com.dharmayard.es.springDataElasticSearch.repositories" />
<!-- spring data elasticsearch DAO 必须依赖 elasticsearchTemplate -->
<bean id="elasticsearchTemplate"
class="org.springframework.data.elasticsearch.core.ElasticsearchTemplate">
<constructor-arg name="client" ref="esClient" />
</bean>
</beans>
3、创建实体类包,对实体进行一些注解标注。并创建dao接口包,它只需要继承ElasticSearchRepository接口。然后就可以开始编写测试代码了
package com.dharmayard.es.springDataElasticSearch.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.FieldType;
@Document(indexName = "test_index2",type = "article")
public class Article {
@Id
@Field(type = FieldType.Long , store = true)
private long id;
@Field(type = FieldType.text , store = true,analyzer = "ik_smart")
private String title;
@Field(type = FieldType.text , store = true,analyzer = "ik_smart")
private String content;
}
package com.dharmayard.es.springDataElasticSearch.repositories;
import com.dharmayard.es.springDataElasticSearch.domain.Article;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
public interface ArticleRepository extends ElasticsearchRepository<Article,Long> {
}
4、编写测试类,在test包下建类并注解上spring容器的测试注解。
import com.dharmayard.es.springDataElasticSearch.domain.Article;
import com.dharmayard.es.springDataElasticSearch.repositories.ArticleRepository;
import com.dharmayard.es.springDataElasticSearch.service.ArticleService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
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"})
//@ContextConfiguration("applicationContext.xml")
public class SpringDataElasticSearchTest {
@Autowired
private ArticleRepository articleRepository;
@Autowired
private ElasticsearchTemplate elasticsearchTemplate;
@Autowired
private ArticleService articleService;
//创建索引
@Test
public void createIndex() {
//创建索引
elasticsearchTemplate.createIndex(Article.class);
//创建映射
elasticsearchTemplate.putMapping(Article.class);
}
//创建文档
@Test
public void createDoc() {
for (int i = 2; i < 20; i++) {
Article ac=new Article();
ac.setId(i);
ac.setTitle("testSave"+i);
ac.setContent("仅仅只是在测试test"+i);
//文档操作
articleService.save(ac);
}
}
//删除文档
@Test
public void deleteDoc(){
articleService.deleteById(2);
}
//修改文档的话相当于再添加一次文档,保持id相同就可以
@Test
public void updateDoc() {
Article ac=new Article();
long id = 3;
ac.setId(id);
ac.setTitle("testUpdate"+id);
ac.setContent("修改test"+id);
//文档操作
articleService.save(ac);
}
/** ----------------- 查询方法 ----------------- **/
//查询所有文档
@Test
public void searchDoc() {
//文档操作
articleService.findAll();
}
//id查询文档
@Test
public void searchDoc01() {
//文档操作
articleService.findById(3);
}
//data jpa规范的命名规范自定义查询:可以对搜索内容先分词然后再查询,但是每个词之间是and关系。
@Test
public void searchDocDefineByJpaName() {
articleService.findByTitle("testSave5");
}
//原生的查询条件NativeSearchQuery对象,根据内容的分词进行查询:创建NativeSearchQuery对象再使用ESTemplate执行查询
@Test
public void searchDocNativeSearchQuery() {
articleService.findByTitle2("test");
}
@Test //查询文档
public void searchDoc04() {
PageRequest pr=new PageRequest(1, 3);
// PageRequest pr=new PageRequest(1, 4,new Sort(Sort.Direction.DESC, "id"));
//分页查询 按照降序排序
articleService.findAll(pr);
}
}
package com.dharmayard.es.springDataElasticSearch.service;
import com.dharmayard.es.springDataElasticSearch.domain.Article;
import org.springframework.data.domain.PageRequest;
public interface ArticleService {
void save(Article ac);
void findAll();
void findById(Integer i);
void findAll(PageRequest pr);
void findByTitle(String string);
void findByTitle2(String string);
void deleteById(Integer id);
}
package com.dharmayard.es.springDataElasticSearch.service.impl;
import com.dharmayard.es.springDataElasticSearch.domain.Article;
import com.dharmayard.es.springDataElasticSearch.repositories.ArticleRepository;
import com.dharmayard.es.springDataElasticSearch.service.ArticleService;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.WildcardQueryBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.stereotype.Service;
@Service
public class ArticleServiceImpl implements ArticleService {
@Autowired
private ArticleRepository articleRepository;
public void save(Article ac) {
articleRepository.save(ac);
}
public void findAll() {
Iterable<Article> all = articleRepository.findAll();
for (Article article : all) {
System.out.println(article);
}
}
public void findById(Integer i) {
Article article = articleRepository.findById(i);
System.out.println(article);
}
public void findAll(PageRequest pr) {
Page<Article> page = articleRepository.findAll(pr);
System.out.println(page.getContent());
}
public void findByTitle(String string) {
//datajpa规范的命名方法
Article testSave = articleRepository.findByTitle(string);
System.out.println(testSave);
}
public void findByTitle2(String string) {
//需要根据内容的分词进行查询
QueryBuilder query= new WildcardQueryBuilder("title", "*"+string+"*");
SearchQuery searchQuery = new NativeSearchQuery(query);
PageRequest pr=new PageRequest(0, 4);
// PageRequest pr=new PageRequest(0, 4,new Sort(Sort.Direction.DESC, "id"));
searchQuery.setPageable(pr);
Page<Article> page = articleRepository.search(searchQuery);
System.out.println(page.getContent());
}
@Override
public void deleteById(Integer id) {
articleRepository.deleteById((long)id);
System.out.println("deleteById success remove id="+id);
}
}
package com.dharmayard.es.springDataElasticSearch.repositories;
import com.dharmayard.es.springDataElasticSearch.domain.Article;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
public interface ArticleRepository extends ElasticsearchRepository<Article,Long> {
Article findById(Integer i);
Article findByTitle(String title);
}