Spring Data Elasticsearch 集成部分源码解析

Elasticsearch是一个基于Lucene的搜索服务器,主要是用于大数据、分布式系统中。

它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。Elasticsearch是用Java开发的,并作为Apache许可条款下的开放源码发布,是当前流行的企业级搜索引擎。设计用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。

在进一步使用 Elasticsearch 之前,让我们先了解几个关键概念。

在逻辑层面:

  • Index (索引):这里的 Index 是名词,一个 Index 就像是传统关系数据库的 Database,它是 Elasticsearch 用来存储数据的逻辑区域
  • Document (文档):Elasticsearch 使用 JSON 文档来表示一个对象,就像是关系数据库中一个 Table 中的一行数据
  • Type (类型):文档归属于一种 Type,就像是关系数据库中的一个 Table
  • Field (字段):每个文档包含多个字段,类似关系数据库中一个 Table 的列

我们用一个表格来做类比,如下:

ElasticsearchMySQL
IndexDatabase
TypeTable
DocumentRow
FieldColumn

在物理层面:

  • Node (节点):node 是一个运行着的 Elasticsearch 实例,一个 node 就是一个单独的 server
  • Cluster (集群):cluster 是多个 node 的集合
  • Shard (分片):数据分片,一个 index 可能会存在于多个 shard

使用的方式主要两种:
① 一种是经过 SpringData 封装过的,直接在 dao 接口继承 ElasticsearchRepository 即可
② 一种是经过 Spring 封装过的,直接在 Service/Controller 中引入该 bean 即可,如下:

@Autowired
	ElasticsearchTemplate elasticsearchTemplate;

上篇的ES Demo部分源码解析:

一.  创建查询的Bean实体

package com.elastic.bean;

import java.io.Serializable;
import java.util.Date;

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;

/**
 * 通过注解配置,与Repository联用时,可以直接将数据结构映射到ElasticSearch上
 * index:是否设置索引, store是否存储数据,type:数据类型,analyzer:分词粒度选择,searchAnalyzer:查询进行分词处理
 *
 */
@Document(indexName = "stu", type = "doc")
public class Stu implements Serializable {

	private static final long serialVersionUID = 5388951762466627197L;

	@Id
	@Field(index=true, store = true, type = FieldType.Long)
	private Long id;

	@Field(index = true, analyzer = "ik_max_word", store = true, searchAnalyzer = "ik_max_word", type = FieldType.Text)
	private String stuId;

	@Field(index = true, analyzer = "ik_max_word", store = true, searchAnalyzer = "ik_max_word", type = FieldType.Text)
	private String stuName;

	@Field(index = true, store = true, type = FieldType.Date)
	private Date createTime;

	public Stu() {
	}
	
	public Stu(Long id, String stuId, String stuName, Date createTime) {
		this.id = id;
		this.stuId = stuId;
		this.stuName = stuName;
		this.createTime = createTime;
	}

	public Long getId() {
		return id;
	}

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

	public String getStuId() {
		return stuId;
	}

	public void setStuId(String stuId) {
		this.stuId = stuId;
	}

	public String getStuName() {
		return stuName;
	}

	public void setStuName(String stuName) {
		this.stuName = stuName;
	}

	public Date getCreateTime() {
		return createTime;
	}

	public void setCreateTime(Date createTime) {
		this.createTime = createTime;
	}
	
}

二.  创建Dao层的StudentRepository

package com.elastic.repository;

import java.util.List;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import org.springframework.stereotype.Repository;

import com.elastic.bean.Stu;

@Repository
public interface StudentRepository extends ElasticsearchRepository<Stu, Long> {
	
	 /**
     * @param stuId
     * @return
     */
	List<Stu> getByStuId(String stuId);
	
    /**
     * @param stuName
     * @return
     */
    List<Stu> getListByStuName(String stuName);

    /**
     * @param stuName
     * @param pageable
     * @return
     */
    Page<Stu> getPageByStuName(String stuName, Pageable pageable);
    
}

 三.  EsServiceImp实现

主要包括Dao 接口继承 ElasticsearchRepository和使用ElasticsearchTemplate模版方法两种方法来进行ES的增删改查

package com.elastic.service.imp;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

import javax.annotation.Resource;

import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.query.IndexQuery;
import org.springframework.data.elasticsearch.core.query.IndexQueryBuilder;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.stereotype.Service;

import com.elastic.bean.Stu;
import com.elastic.repository.StudentRepository;
import com.elastic.service.EsService;

@Service("esService ")
public class EsServiceImp implements EsService {


	/**
	 * 1. Dao层的StudentRepository
	 */
	@Resource
	private StudentRepository repository;

	/**
	 * 2. 模版方法
	 */
	@Autowired
	private ElasticsearchTemplate template;

	@Override
	public void save(Stu stu) {
		repository.save(stu);
	}

	@Override
	public Stu findById(Long id) {
		Stu rtn = null;
		Optional<Stu> stu = repository.findById(id);
		if (stu.isPresent()) {
			rtn = stu.get();
		}
		return rtn;
	}

	@Override
	public List<Stu> getByStuId(String stuId) {
		return repository.getByStuId(stuId);
	}

	@Override
	public List<Stu> getByStuName(String stuName) {
		return repository.getListByStuName(stuName);
	}


	// region Template Methods

	@Override
	public void save(String indexname, String type, Object obj) {
		IndexQuery indexquery = new IndexQueryBuilder()
				.withIndexName(indexname).withType(type).withObject(obj)
				.build();
		template.index(indexquery);
	}

	@Override
	public void delete(String indexname, String type, String id) {
		template.delete(indexname, type, id);
	}
	
	@Override
	public void update(String indexname, String type, Object obj) {
		IndexQuery indexquery = new IndexQueryBuilder()
				.withIndexName(indexname).withType(type).withObject(obj)
				.build();
		template.index(indexquery);
	}

	@Override
	public <T> List<T> findBySort(Class<T> clazz) {
		Sort sort = new Sort(Sort.Direction.DESC, "id");
		Pageable pageable = PageRequest.of(0, 10, sort);
		SearchQuery searchquery = new NativeSearchQueryBuilder()
				.withQuery(QueryBuilders.matchAllQuery())
				.withPageable(pageable).build();
		Page<T> items = template.queryForPage(searchquery, clazz);
		return items.getContent();
	}

	// endregion Template Methods

}

四:Controller测试

package com.elastic.controller;

import java.util.Date;
import java.util.List;

import javax.annotation.Resource;

import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import com.elastic.bean.Book;
import com.elastic.bean.Stu;
import com.elastic.service.EsService;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
@RequestMapping("/es")
public class EsController {
    
   
   	/**
	 * 通过两种方法来增删改查ES的数据
	 * 
	 * 1. Dao 接口继承 ElasticsearchRepository
	 * 2. 使用ElasticsearchTemplate模版方法
	 */
	
	@Resource
	private EsService esService;
	
	// region Repository Methods

	
	@ResponseBody
	@RequestMapping(value = "/findByStuId", method = RequestMethod.GET)
	public List<Stu> findByStuId(String stuName){
		// 分页参数,排序
		Sort sort = new Sort(Sort.Direction.ASC, "id");
		Pageable pageable = PageRequest.of(0, 2, sort);
		List<Stu> listpages = esService.getPageByStuName(stuName, pageable);

		return listpages;
	}

	@RequestMapping(value = "/delete", method = RequestMethod.POST)
	public String delete(){
		Stu stu = esService.findById(7L);
		esService.delete(stu);

		return "删除成功";
	}
	
	// endregion Repository Methods
	
	// region Template Methods
	
	@RequestMapping(value = "/savebook", method = RequestMethod.POST)
	public String savebook(){
		String[] names = {"《西游记》","《红楼梦》","《三国演义》","《水浒传》","《西厢记》"};
		String[] persons = {"猴子","宝玉","曹操","武松","张生"};
		for(int i = 0; i < names.length; i++){
			Book book = new Book(i+1, names[i], persons[i]);
			esService.save("library", "book", book);
		}
		return "保存成功";
	}
	
	@RequestMapping(value = "/deletebook", method = RequestMethod.POST)
	public void deletebook(){
		Book book = new Book(1,"《西游记》","猪小戒");
		esService.delete("library", "book", String.valueOf(book.getId()));
	}
	
	@RequestMapping(value = "/updatebook", method = RequestMethod.POST)
	public void updatebook(){
		Book book = new Book(1,"《西游记》","猪小戒");
		esService.update("library", "book", book);
	}
	
	@RequestMapping(value = "/findbook", method = RequestMethod.POST)
	public void findbook(){
		List<Book> books = esService.findBySort(Book.class);
		System.out.println(books.size());
	}
	
	// endregion Template Methods
	
}

上面的源码下载地址见上一篇文章

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值