spring data elasticsearch

elasticsearch

2.0.0.RELEASE

2.2.0

1.4.0.M1

1.7.3

1.3.0.RELEASE

1.5.2

1.2.0.RELEASE

1.4.4

1.1.0.RELEASE

1.3.2

1.0.0.RELEASE

​https://github.com/helloworldtang/spring-data-elasticsearch​

1、None of the configured nodes are available 或者

  org.elasticsearch.transport.RemoteTransportException: Failed to deserialize exception response from stream

 原因:spring data elasticSearch 的版本与Spring boot、Elasticsearch版本不匹配。

 解决:

Spring Boot Version (x)

Spring Data Elasticsearch Version (y)

Elasticsearch Version (z)

x <= 1.3.5

y <= 1.3.4

z <= 1.7.2*

x >= 1.4.x

2.0.0 <=y < 5.0.0**

2.0.0 <= z < 5.0.0**

    这是版本之间的对应关系。Spring boot 1.3.5默认的elasticsearch版本是1.5.2,此时启动1.7.2版本以下的Elasticsearch客户端连接正常。

  注:注意java的es默认连接端口是9300,9200是http端口,这两个在使用中应注意区分。

2、Caused by: java.lang.IllegalArgumentException: @ConditionalOnMissingBean annotations must specify at least one bean (type, name or annotation)

  原因:spring boot是1.3.x版本,而es采用了2.x版本。在es的2.x版本去除了一些类,而这些类在spring boot的1.3.x版本中仍然被使用,导致此错误。

  解决:依照问题1中的版本对应关系,启动特定版本的es即可。

 

The Integration Zone is brought to you in partnership with ​​3scale​​​. Take control of your APIs and get a free t-shirt when you complete the ​​3step Challenge​​. 

We often use Elasticsearch to improve performance in our application, especially searching and caching, to make our application scale and adapt in real-time.

Elasticsearch is a flexible and powerful open source, distributed, real-time search and analytics engine. In this article, I would like to introduce how to use Elasticsearch in java applications: by using Spring Boot data Elasticsearch. Spring Boot now easy and powerful, and we can build fast Java and web applications with a simple configuration.

By following the steps below, you can start writing your first application.

Source code: ​​https://github.com/herotl2005/spring-data-elasticsearch-sample​

Requirement enviroment

1. Install Elasticsearch

2. Install Gradle

3. IDE Eclipse or Intellij  IDEA

Step by Step Coding

1. Gradle build 

dependencies {
testCompile group: 'junit', name: 'junit', version: '4.11'
compile 'org.springframework.boot:spring-boot-starter-data-elasticsearch:1.2.0.RELEASE'
compile 'org.springframework.data:spring-data-cassandra:1.1.1.RELEASE'
compile 'org.springframework:spring-test:4.1.2.RELEASE'
compile 'org.springframework.boot:spring-boot-starter-logging:1.2.0.RELEASE'
compile 'org.springframework.boot:spring-boot-starter-web:1.2.0.RELEASE'
compile 'org.springframework.boot:spring-boot-starter-actuator:1.2.0.RELEASE'
}

2. Elasticsearch configuration

@Configuration@PropertySource(value = "classpath:elasticsearch.properties")
@EnableElasticsearchRepositories(basePackages = "co.paan.repository")
public class ElasticsearchConfiguration {
@Resource
private Environment environment;
@Bean
public Client client() {
TransportClient client = new TransportClient();
TransportAddress address = new InetSocketTransportAddress(environment.getProperty("elasticsearch.host"), Integer.parseInt(environment.getProperty("elasticsearch.port")));
client.addTransportAddress(address);
return client;
}

@Beanpublic ElasticsearchOperations elasticsearchTemplate() {
return new ElasticsearchTemplate(client());
}
}

 

You put elasticsearch host and post in your application properties file.

elasticsearch.host = localhost
# if you use you local elasticsearch host
elasticsearch.port = 9300

 

3. Data mapping object: 

In this application, we have 2 entities data object mapping: Post and Tag

@Document(indexName = "post", type = "post", shards = 1, replicas = 0)
public class Post {
@Idprivate String id; private String title;//
@Field(type= FieldType.Nested)
private List<Tag> tags;
public String getId() {
return id;
}

public void setId(String id) {
this.id = id;
}

public String getTitle() {
return title;
}

public void setTitle(String title) {
this.title = title;
}

public List<Tag> getTags() {
return tags;
}

public void setTags(List<Tag> tags) {
this.tags = tags;}
}

 

public class Tag {
private String id;
private String name;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}
}

4. Repository: we extends from ElasticsearchRepository

public interface PostRepository extends ElasticsearchRepository<Post, String>{

Page<Post> findByTagsName(String name, Pageable pageable);
}

 

5. Data access service

public interface PostService {
Post save(Post post);
Post findOne(String id);
Iterable<Post> findAll();
Page<Post> findByTagsName(String tagName, PageRequest pageRequest);
}

 

@Servicepublic class PostServiceImpl implements PostService{
@Autowired
private PostRepository postRepository;
@Override
public Post save(Post post) {
postRepository.save(post);

return post;
}

@Overridepublic Post findOne(String id) {
return postRepository.findOne(id);
}

@Overridepublic Iterable<Post> findAll() {
return postRepository.findAll();
}

@Overridepublic Page<Post> findByTagsName(String tagName, PageRequest pageRequest) {
return postRepository.findByTagsName(tagName, pageRequest);
}
}

6. Testing and the result

@Testpublic void testFindByTagsName() throws Exception {
Tag tag = new Tag();
tag.setId("1");
tag.setName("tech");
Tag tag2 = new Tag();
tag2.setId("2");
tag2.setName("elasticsearch");
Post post = new Post();
post.setId("1");
post.setTitle("Bigining with spring boot application and elasticsearch");
post.setTags(Arrays.asList(tag, tag2));
postService.save(post);
Post post2 = new Post();
post2.setId("1");
post2.setTitle("Bigining with spring boot application");
post2.setTags(Arrays.asList(tag));
postService.save(post);
Page<Post> posts = postService.findByTagsName("tech", new PageRequest(0,10));Page<Post> posts2 = postService.findByTagsName("tech", new PageRequest(0,10));Page<Post> posts3 = postService.findByTagsName("maz", new PageRequest(0,10));assertThat(posts.getTotalElements(), is(1L));
assertThat(posts2.getTotalElements(), is(1L));
assertThat(posts3.getTotalElements(), is(0L));
}

7. You can find detail project at github: ​​https://github.com/herotl2005/spring-data-elasticsearch-sample​

The Integration Zone is brought to you in partnership with ​​3scale​​​. Learn how API providers have changed the way we think about integration in ​​The Platform Vision of API Giants​​.

https://dzone.com/articles/first-step-spring-boot-and

spring data elasticsearch 查询方式:

1、通过名字解析

public​​​ ​​interface​​​ ​​BookRepository ​​​​extends​​​ ​​Repository<Book, String>​​
​​{​​
​​List<Book> findByNameAndPrice(String name, Integer price);​​
​​}​​
​​根据上面的方法名会生成下面的Elasticsearch查询语句​​
​​{ ​​​​"bool"​​​ ​​:​​
​​{ ​​​​"must"​​​ ​​:​​
​​[​​
​​{ ​​​​"field"​​​ ​​: {​​​​"name"​​​ ​​: ​​​​"?"​​​​} },​​
​​{ ​​​​"field"​​​ ​​: {​​​​"price"​​​ ​​: ​​​​"?"​​​​} }​​
​​]​​
​​}​​
​​}​​

2、@query注解

​​public​​​ ​​interface​​​ ​​BookRepository ​​​​extends​​​ ​​ElasticsearchRepository<Book, String> {​​
​​@Query​​​​(​​​​"{"​​​​bool​​​​" : {"​​​​must​​​​" : {"​​​​field​​​​" : {"​​​​name​​​​" : "​​​​?​​​​0​​​​"}}}}"​​​​)​​
​​Page<Book> findByName(String name,Pageable pageable);​​
​​}​​

3、构建Filter

​​使用过滤器可以提高查询速度+​​

​​private​​​ ​​ElasticsearchTemplate elasticsearchTemplate;​​

​​SearchQuery searchQuery = ​​​​new​​​ ​​NativeSearchQueryBuilder()​​
​​.withQuery(matchAllQuery())​​
​​.withFilter(boolFilter().must(termFilter(​​​​"id"​​​​, documentId)))​​
​​.build();​​

​​Page<SampleEntity> sampleEntities =​​
​​elasticsearchTemplate.queryForPage(searchQuery,SampleEntity.​​​​class​​​​);​​

利用Scan和Scroll处理大结果集

Elasticsearch在处理大结果集时可以使用scan和scroll。在Spring Data Elasticsearch中,可以向下面那样使用ElasticsearchTemplate来使用scan和scroll处理大结果集。

Example 39. Using Scan and Scroll(使用scan和scroll)

SearchQuery searchQuery = ​​​​new​​​ ​​NativeSearchQueryBuilder()​​
​​.withQuery(matchAllQuery())​​
​​.withIndices(​​​​"test-index"​​​​)​​
​​.withTypes(​​​​"test-type"​​​​)​​
​​.withPageable(​​​​new​​​ ​​PageRequest(​​​​0​​​​,​​​​1​​​​))​​
​​.build();​​
​​String scrollId = elasticsearchTemplate.scan(searchQuery,​​​​1000​​​​,​​​​false​​​​);​​
​​List<SampleEntity> sampleEntities = ​​​​new​​​ ​​ArrayList<SampleEntity>();​​
​​boolean​​​ ​​hasRecords = ​​​​true​​​​;​​
​​while​​​ ​​(hasRecords){​​
​​Page<SampleEntity> page = elasticsearchTemplate.scroll(scrollId, 5000L , ​​​​new​​​ ​​ResultsMapper<SampleEntity>()​​
​​{​​
​​@Override​​
​​public​​​ ​​Page<SampleEntity> mapResults(SearchResponse response) {​​
​​List<SampleEntity> chunk = ​​​​new​​​ ​​ArrayList<SampleEntity>();​​
​​for​​​​(SearchHit searchHit : response.getHits()){​​
​​if​​​​(response.getHits().getHits().length <= ​​​​0​​​​) {​​
​​return​​​ ​​null​​​​;​​
​​}​​
​​SampleEntity user = ​​​​new​​​ ​​SampleEntity();​​
​​user.setId(searchHit.getId());​​
​​user.setMessage((String)searchHit.getSource().get(​​​​"message"​​​​));​​
​​chunk.add(user);​​
​​}​​
​​return​​​ ​​new​​​ ​​PageImpl<SampleEntity>(chunk);​​
​​}​​
​​});​​
​​if​​​​(page != ​​​​null​​​​) {​​
​​sampleEntities.addAll(page.getContent());​​
​​hasRecords = page.hasNextPage();​​
​​}​​
​​else​​​​{​​
​​hasRecords = ​​​​false​​​​;​​
​​}​​
​​}​​
​​}​​