Spring Data Elasticsearch项目将核心Spring概念应用于使用Elasticsearch搜索引擎开发解决方案。为我们提供了一个“模板”作为高级抽象,用于存储、查询、排序和面对文档.
要使用Spring Data Elasticsearch为我们设计好的模板,只需继承ElasticsearchRepository
如:
public interface ElasticsearchMapper extends ElasticsearchRepository<Blog,Integer>{
}
可以看到ElasticsearchRepository实现了CrudRepository这个接口
Spring Data repository抽象中的中心接口是Repository。它将领域类和领域类的ID类型作为类型参数来管理。此接口主要用作标记接口,以捕获要使用的类型,并帮助您发现扩展此接口的接口。CrudRepository为所管理的实体类提供了复杂的CRUD功能。
CrudRepository:
public interface CrudRepository<T, ID extends Serializable>
extends Repository<T, ID> {
<S extends T> S save(S entity);
Optional<T> findById(ID primaryKey);
Iterable<T> findAll();
long count();
void delete(T entity);
boolean existsById(ID primaryKey);
// … more functionality omitted.
}
在CrudRepository之上,有一个PagingAndSortingRepository抽象,它添加了额外的方法来简化对实体的分页访问:
public interface PagingAndSortingRepository<T, ID extends Serializable>
extends CrudRepository<T, ID> {
/**
* 根据所给排序规则返回对应的实体类
*
* @param sort
* @return all entities sorted by the given options
*/
Iterable<T> findAll(Sort sort);
/**
* 根据所给排序规则返回对应的实体类的分页集合
*
* @param pageable
* @return a page of entities
*/
Page<T> findAll(Pageable pageable);
}
如:
public interface BookRepository extends Repository<Book, String>
{
List<Book> findByNameAndPrice(String name, Integer price);
}
上面的方法名将被转换为下面的Elasticsearch json查询:
{ "bool" :
{ "must" :
[
{ "field" : {"name" : "?"} },
{ "field" : {"price" : "?"} }
]
}
}
还可以使用@Query注释在方法中声明查询。
public interface BookRepository extends ElasticsearchRepository<Book, String> {
@Query("{"bool" : {"must" : {"field" : {"name" : "?0"}}}}")
Page<Book> findByName(String name,Pageable pageable);
}
详细的文档说明:
https://docs.spring.io/spring-data/elasticsearch/docs/current/reference/html/#elasticsearch.misc
以下为对针对自定义实体类Blog基本操作的测试:
Blog
@AllArgsConstructor
@NoArgsConstructor
@Setter
@Getter
@Document(indexName = "test", type = "blog")
public class Blog {
private Integer id;
private String title;
private String content;
private Integer commentSize;
private Timestamp createTime;
private Integer readSize;
private Integer voteSize;
}
继承ElasticsearchRepository接口:
public interface ElasticsearchMapper extends ElasticsearchRepository<Blog,Integer>{
List<Blog> findByTitle(String title);
List<Blog> findByTitleContaining(String title);
List<Blog> findByReadSizeBetween(Integer from,Integer to);
Optional<Blog> findById(Integer id);
List<Blog> findByTitleStartingWith(String title);
}
Service:
@Service("EsService")
public class EsService {
@Autowired
private ElasticsearchMapper elasticsearchMapper;
/*/**
* 保存Blog
* @param [blog]
* @return void
* @exception
*/
public void save(Blog blog){
elasticsearchMapper.save(blog);
}
/*/**
* 根据 title 来查找Blog
* @param [title]
* @return java.util.List
* @exception
*/
public List<Blog> queryByTitle(String title){
return elasticsearchMapper.findByTitle(title);
}
/*/**
* 根据 title 来查找Blog
* @param [title]
* @return java.util.List
* @exception
*/
public List<Blog> queryByTitleContaining(String title){
return elasticsearchMapper.findByTitleContaining(title);
}
/*/**
* 根据范围 查找 blog
* @param [from, to]
* @return java.util.List
* @exception
*/
public List<Blog> queryByReadSizeBetween(Integer from,Integer to){
return elasticsearchMapper.findByReadSizeBetween(from,to);
}
/*/**
* 根据id 查找
* @param [id]
* @return java.util.Optional
* @exception
*/
public Optional<Blog> queryById(Integer id){
return elasticsearchMapper.findById(id);
}
/*/**
* 针对readSize字段 按降序进行查找
* @param []
* @return java.lang.Iterable
* @exception
*/
public Iterable<Blog> getAll(){
Sort sort = new Sort(Sort.Direction.DESC,"readSize");
return elasticsearchMapper.findAll(sort);
}
/*/**
* 按时间排序查找 从最新的文章开始往下排
* @param []
* @return java.lang.Iterable
* @exception
*/
public Iterable<Blog> getAllBycreateTime(){
Sort sort = new Sort(Sort.Direction.DESC,"createTime");
return elasticsearchMapper.findAll(sort);
}
/*/**
* 使用 QueryBuilder进行匹配查询
* @param []
* @return java.lang.Iterable
* @exception
* termQuery 匹配查询 前者为实体类的字段 后者为你希望匹配的内容
*fuzzyQuery 模糊匹配 前者为实体类的字段 后者为你希望匹配的内容 只要出现了value 就可以匹配
*/
public Iterable<Blog> searchQuery(){
QueryBuilder queryBuilder = QueryBuilders.termQuery("title", "Web");
QueryBuilder queryBuilder1 = QueryBuilders.fuzzyQuery("title", "人");
return elasticsearchMapper.search(queryBuilder1);
}
/*/**
* 以***为开始来进行匹配标题
* @param [title]
* @return java.util.List
* @exception
*/
public List<Blog> queryByTitleStartingWith(String title){
return elasticsearchMapper.findByTitleStartingWith(title);
}
/*/**
* 通过id 删除实体
* @param [id]
* @return void
* @exception
*/
public void delete(Integer id){
elasticsearchMapper.deleteById(id);
}
}
测试
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = EsdemoApplication.class)
@TestPropertySource(locations = "classpath:application.properties")//加载配置文件
@Slf4j
public class Test {
@Autowired
private EsService esService;
/*/**
* 测试 保存操作
* @param []
* @return void
* @exception
*/
@org.junit.Test
public void T1(){
List<Blog> blogs = DataSource.offerBlogs();
for(Blog blog : blogs){
esService.save(blog);
}
}
/*/**
* 匹配查询
* @param []
* @return void
* @exception
*/
@org.junit.Test
public void Testquery1(){
List<Blog> blogs = esService.queryByTitle("告别BAT?迎来ATM?");
log.info("{}",blogs.size());
for(Blog blog:blogs){
log.info("{}",blog.getContent());
}
}
/*/**
* 匹配查询
* @param []
* @return void
* @exception
*/
@org.junit.Test
public void TestQueryContainging(){
List<Blog> blogs = esService.queryByTitleContaining("告别BAT?迎来ATM?");
log.info("{}",blogs.size());
for(Blog blog:blogs){
log.info("{}",blog.getContent());
}
}
/*/**
* 针对readSize 范围查找
* @param []
* @return void
* @exception
*/
@org.junit.Test
public void TestByReadSizeBetween(){
List<Blog> blogs = esService.queryByReadSizeBetween(100,900);
log.info("{}",blogs.size());
for(Blog blog:blogs){
log.info("{}",blog.getContent());
}
}
/*/**
* 根据id 查找
* @param []
* @return void
* @exception
*/
@org.junit.Test
public void TestQueryById(){
Optional<Blog> blog = esService.queryById(6);
log.info("{}",blog.get().getContent());
}
/*/**
* 根据readSize 降序查找
* @param []
* @return void
* @exception
*/
@org.junit.Test
public void TestfindAll(){
Iterable<Blog> iterable = esService.getAll();
Iterator<Blog> iterator = iterable.iterator();
while (iterator.hasNext()){
Blog blog = iterator.next();
log.info("{}",blog.getTitle()+" "+blog.getReadSize());
}
}
@org.junit.Test
public void TestsearchQuery(){
Iterable<Blog> iterable = esService.searchQuery();
Iterator<Blog> iterator = iterable.iterator();
while (iterator.hasNext()){
Blog blog = iterator.next();
log.info("{}",blog.getTitle()+" "+blog.getReadSize());
}
}
/*/**
* 按时间先后排序查找
* @param []
* @return void
* @exception
*/
@org.junit.Test
public void TestgetAllBycreateTime(){
Iterable<Blog> iterable = esService.getAllBycreateTime();
Iterator<Blog> iterator = iterable.iterator();
while (iterator.hasNext()){
Blog blog = iterator.next();
log.info("{}",blog.getTitle()+" "+blog.getCreateTime());
}
}
/*/**
* 以***为开始来进行匹配标题
* @param []
* @return void
* @exception
*/
@org.junit.Test
public void TestqueryByTitleStartingWith(){
List<Blog> blogs = esService.queryByTitleStartingWith("告别");
for(Blog blog : blogs){
log.info("{}",blog.getTitle());
}
}
/*/**
* 根据id 进行删除操作
* @param []
* @return void
* @exception
*/
@org.junit.Test
public void Testdelete(){
esService.delete(6);
}
}