当前位置: 代码迷 >> 综合 >> Spring Data Elasticsearch 集成部分源码解析
  详细解决方案

Spring Data Elasticsearch 集成部分源码解析

热度:11   发布时间:2023-12-15 01:00:38.0

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

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

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

在逻辑层面:

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

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

Elasticsearch MySQL
Index Database
Type Table
Document Row
Field Column

在物理层面:

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

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

@AutowiredElasticsearchTemplate 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*/@Resourceprivate StudentRepository repository;/*** 2. 模版方法*/@Autowiredprivate ElasticsearchTemplate template;@Overridepublic void save(Stu stu) {repository.save(stu);}@Overridepublic Stu findById(Long id) {Stu rtn = null;Optional<Stu> stu = repository.findById(id);if (stu.isPresent()) {rtn = stu.get();}return rtn;}@Overridepublic List<Stu> getByStuId(String stuId) {return repository.getByStuId(stuId);}@Overridepublic List<Stu> getByStuName(String stuName) {return repository.getListByStuName(stuName);}// region Template Methods@Overridepublic void save(String indexname, String type, Object obj) {IndexQuery indexquery = new IndexQueryBuilder().withIndexName(indexname).withType(type).withObject(obj).build();template.index(indexquery);}@Overridepublic void delete(String indexname, String type, String id) {template.delete(indexname, type, id);}@Overridepublic void update(String indexname, String type, Object obj) {IndexQuery indexquery = new IndexQueryBuilder().withIndexName(indexname).withType(type).withObject(obj).build();template.index(indexquery);}@Overridepublic <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模版方法*/@Resourceprivate 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}

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

  相关解决方案