Spring Data Elasticsearch介绍

1 资料收集

官方文档中文翻译

http://es.xiaoleilu.com/index.html

https://endymecy.gitbooks.io/elasticsearch-guide-chinese/content/index.html

官方英文文档

https://www.elastic.co/guide/en/elasticsearch/client/java-api/current/java-docs-index.html

Spring Data Elasticsearch

http://docs.spring.io/spring-data/elasticsearch/docs/2.0.2.RELEASE/reference/html/#repositories.limit-query-result

2 Spring Data Elasticsearch提供功能

2.1 支持jpa

2.2 普通curd查询

public interface CrudRepository<T, ID extends Serializable>
    extends Repository<T, ID> {
    //保存
    <S extends T> S save(S entity); 
//通过id查找
    T findOne(ID primaryKey);       
//获取所有对象
    Iterable<T> findAll();          
//获取的count
    Long count();                   
//删除
    void delete(T entity);          
//判断是否存在
    boolean exists(ID primaryKey);  

    // … more functionality omitted.
}

2.2 分页查询

简单分页查询

public interface PagingAndSortingRepository<T, ID extends Serializable>
  extends CrudRepository<T, ID> {
  //排序查询所有的数据
  Iterable<T> findAll(Sort sort);
//分页查询
  Page<T> findAll(Pageable pageable);
}

比如想要查询前20条数据

PagingAndSortingRepository<User, Long> repository = // … get access to a bean
Page<User> users = repository.findAll(new PageRequest(1, 20));

复杂带条件分页查询

Page<User> findByLastname(String lastname, Pageable pageable);

Slice<User> findByLastname(String lastname, Pageable pageable);

List<User> findByLastname(String lastname, Sort sort);

List<User> findByLastname(String lastname, Pageable pageable);

2.3 通用规范自定义查询

根据方法名字,自动查询,比如获取lastname为参数的数量

public interface UserRepository extends CrudRepository<User, Long> {

  Long countByLastname(String lastname);
}

根据属性删除数据

public interface UserRepository extends CrudRepository<User, Long> {

  Long deleteByLastname(String lastname);

  List<User> removeByLastname(String lastname);

}

查询例子

interface PersonRepository extends Repository<Person, Long> {
  List<Person> findByLastname(String lastname);
}

public interface PersonRepository extends Repository<User, Long> {

  List<Person> findByEmailAddressAndLastname(EmailAddress emailAddress, String lastname);

  // Enables the distinct flag for the query
  List<Person> findDistinctPeopleByLastnameOrFirstname(String lastname, String firstname);
  List<Person> findPeopleDistinctByLastnameOrFirstname(String lastname, String firstname);

  // Enabling ignoring case for an individual property
  List<Person> findByLastnameIgnoreCase(String lastname);
  // Enabling ignoring case for all suitable properties
  List<Person> findByLastnameAndFirstnameAllIgnoreCase(String lastname, String firstname);

  // Enabling static ORDER BY for a query
  List<Person> findByLastnameOrderByFirstnameAsc(String lastname);
  List<Person> findByLastnameOrderByFirstnameDesc(String lastname);
}

2.4 定义自己的通用repository

如果extend extend Repository, CrudRepository or PagingAndSortingRepository., CrudRepository or PagingAndSortingRepository. 这些都不满足你的通用自定义Repository,可以通过使用@NoRepositoryBean来定义通用自定义repository

@NoRepositoryBean
interface MyBaseRepository<T, ID extends Serializable> extends Repository<T, ID> {

  T findOne(ID id);

  T save(T entity);
}

interface UserRepository extends MyBaseRepository<User, Long> {
  User findByEmailAddress(EmailAddress emailAddress);
}

2.5 支持java8 stream查询

这个我比较好奇,这个文档写到了spring data elasticsearch中,难道还支持sql,表示没有尝试过

@Query("select u from User u")
Stream<User> findAllByCustomQueryAndStream();

try (Stream<User> stream = repository.findAllByCustomQueryAndStream()) {
  stream.forEach(…);
}

2.6 支持异步查询

@Async
Future<User> findByFirstname(String firstname);               

@Async
CompletableFuture<User> findOneByFirstname(String firstname); 

@Async
ListenableFuture<User> findOneByLastname(String lastname);

2.7 Web Support

注解方式

@Configuration
@EnableWebMvc
@EnableSpringDataWebSupport
class WebConfiguration { }

xml方式

<bean class="org.springframework.data.web.config.SpringDataWebConfiguration" />

<!-- If you're using Spring HATEOAS as well register this one *instead* of the former -->
<bean class="org.springframework.data.web.config.HateoasAwareSpringDataWebConfiguration" />

支持方式

主要是支持基础的WEB:

  1. 通过DomainClassConverter,允许spring mvc通过request parameters or path variables从repository 注入一个对象,这句话翻译得比较抽象,看看例子就知道了
  2. HandlerMethodArgumentResolver 让spring mvc 支持解析 Pageable and Sort 两个参数

    @Controller
    @RequestMapping("/users")
    public class UserController {
    
    @RequestMapping("/{id}")
    public String showUserForm(@PathVariable("id") User user, Model model) {
    
     model.addAttribute("user", user);
     return "userForm";
    }
    }
    

    上面的User对象是自动根据findOne这个方法从repository中查找对象并注入进去。

    @Controller
    @RequestMapping("/users")
    public class UserController {
    
    @Autowired UserRepository repository;
    
    @RequestMapping
    public String showUsers(Model model, Pageable pageable) {
    
     model.addAttribute("users", repository.findAll(pageable));
     return "users";
    }
    }
    

    上面列子演示了分页查询,可以自动识别参数并且减少很多代码去查询

参数 使用方式
page Page you want to retrieve, 0 indexed and defaults to 0.
size Size of the page you want to retrieve, defaults to 20.
sort sort=firstname&sort=lastname,asc 指定排序字段和方式

2.7 支持注解注解orm的方式去操作对象

@Document(indexName = "tb_article")
public class Article {
    @Id
    private int id;
    @Field(type = FieldType.String, index = FieldIndex.analyzed, store = true)
    private String content;
    @Field(type = FieldType.String, index = FieldIndex.analyzed, store = true)
    private String title;
    @Field(type = FieldType.Date, index = FieldIndex.not_analyzed, store = true)
    private Date updateDate;
}
//保存数据并且索引
ArticleRepository articleRepository = (ArticleRepository) classPathXmlApplicationContext.getBean("articleRepository");
        Article article = new Article();
        article.setContent("2016-07-15 16:51:04,666 [main] DEBUG org.elasticsearch.threadpool - [Speed Demon] creating thread_pool [get], type [fixed], size [4], queue_size [1k]");
        article.setTitle("我是标题");
        article.setId(123);
        articleRepository.save(article);

3 支持Elasticsearch的原生操作

3.1 支持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);

3.2 用Scan And 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;
    }
    }
}

4 配置

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       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/data/elasticsearch http://www.springframework.org/schema/data/elasticsearch/spring-elasticsearch.xsd">


    <elasticsearch:repositories base-package="com.main.com.es.main.repository"

    />

    <elasticsearch:transport-client id="client"
                                    cluster-nodes="192.168.114.109:9300"
                                    cluster-name="searches"
     />
    <bean name="elasticsearchTemplate" class="org.springframework.data.elasticsearch.core.ElasticsearchTemplate">
        <constructor-arg name="client" ref="client"/>
    </bean >
</beans>
@Repository
public interface ArticleRepository extends ElasticsearchRepository<Article, Integer> {
}

ElasticsearchTemplate是一个可以操作原生Elasticsearch 的client的类配置后可以无缝的接入spring

results matching ""

    No results matching ""