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 即可,如下:
@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
}
上面的源码下载地址见上一篇文章