SpringBoot 使用 ElasticSearch 6.x搜索引擎
一、介绍
Elasticsearch (ES)是一个基于Lucene构建的开源、分布式、RESTful 接口全文搜索引擎。Elasticsearch 还是一个分布式文档数据库,其中每个字段均是被索引的数据且可被搜索,它能够扩展至数以百计的服务器存储以及处理PB级的数据。它可以在很短的时间内在储、搜索和分析大量的数据。它通常作为具有复杂搜索场景情况下的核心发动机。
Elasticsearch就是为高可用和可扩展而生的。可以通过购置性能更强的服务器来完成。
二、Elasticsearch优势
-
横向可扩展性:只需要增加台服务器,做一点儿配置,启动一下Elasticsearch就可以并入集群。
-
分片机制提供更好的分布性:同一个索引分成多个分片(sharding), 这点类似于HDFS的块机制;分而治之的方式可提升处理效率。
-
高可用:提供复制( replica) 机制,一个分片可以设置多个复制,使得某台服务器在宕机的情况下,集群仍旧可以照常运行,并会把服务器宕机丢失的数据信息复制恢复到其他可用节点上。
口使用简单:共需一条命令就可以下载文件,然后很快就能搭建一一个站内搜索引擎。
三、Elasticsearch存储结构
Elasticsearch是文件存储,Elasticsearch是面向文档型数据库,一条数据在这里就是一个文档,用JSON作为文档序列化的格式,比如下面这条用户数据
{
"name" : "哈哈哈",
"sex" : 男,
"age" : 10
}
关系数据库 ⇒ 数据库 ⇒ 表 ⇒ 行 ⇒ 列(Columns)
Elasticsearch ⇒ 索引(Index) ⇒ 类型(type) ⇒ 文档(Docments) ⇒ 字段(Fields)
四、Elasticsearch版本控制
- 版本控制
为了保证数据再多线程操作下的准确性 - 悲观锁和乐观锁
悲观锁:假设会发生并发冲突,屏蔽一切可能违反数据准确性的操作
悲观锁:假设不会发生并发冲突,只在提交操作是检查是否违反数据完整性。 - 内部版本控制和外部版本控制
内部版本控制:_version自增长,修改数据后,_version会自动的加1
外部版本控制:为了保持_version与外部版本控制的数值一致
五、环境搭建
Es的环境搭建,在我博客中有介绍,可参考:
https://blog.csdn.net/qq_43692950/article/details/107689309
六、SpringBoot集成Elasticsearch
1. pom
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
2. application.properties
#elasticsearch
spring.data.elasticsearch.cluster-name=elasticsearch
#集群
#spring.data.elasticsearch.cluster-nodes=192.168.2.112:9300,192.168.2.139:9300,192.168.2.133:9300
#单机
spring.data.elasticsearch.cluster-nodes=localhost:9300
spring.data.elasticsearch.repositories.enabled=true
3. Entity
@Document(indexName = "detection",type = "info") //索引名和类型
@Data
public class TakeEntity implements Serializable {
@Id
private long id;
@Field(type = FieldType.text, analyzer = "ik_smart", searchAnalyzer = "ik_smart") //使用ik中文分词器,ik的环境需要配置
private String deviceid;
@Field
private String imgpath;
@Field
private long time;
@Field
private String age;
@Field
private String gender;
}
4. Repository
@Repository
public interface TakeFaceRepository extends ElasticsearchRepository<TakeEntity, Long> {
}
5. Service
public interface DemoService {
boolean save(TakeEntity takeFace);
Iterable<TakeEntity> findall();
void search();
boolean delete();
void update();
}
6. Impl
@Service
public class DemoServiceImpl implements DemoService {
@Autowired
TakeFaceRepository takeFaceRepository;
/*
添加数据
*/
@Override
public boolean save(TakeEntity takeFace) {
try {
//添加单条数据
takeFaceRepository.save(takeFace);
//添加多条数据
List<TakeEntity> list = new ArrayList<>();
list.add(takeFace);
list.add(takeFace);
list.add(takeFace);
takeFaceRepository.saveAll(list);
return true;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
/*
查询数据 find
*/
@Override
public Iterable<TakeEntity> findall() {
//查询全部
Iterable<TakeEntity> all = takeFaceRepository.findAll();
//排序
takeFaceRepository.findAll(Sort.by(Sort.Direction.DESC, "time"));
//分页查询
Pageable pageable1 = PageRequest.of(1, 20);
//分页加排序
Pageable pageable = new PageRequest(1, 20, Sort.by(Sort.Direction.DESC, "time"));
Pageable pageable2 = PageRequest.of(1, 20, Sort.by(Sort.Direction.DESC, "time"));
Pageable pageable3 = PageRequest.of(1, 20, Sort.Direction.DESC, "time");
takeFaceRepository.findAll(pageable);
//根据id查询多个
List<Long> longs = new ArrayList<>();
longs.add(1234L);
takeFaceRepository.findAllById(longs);
return all;
}
/*
条件查询
*/
public void search() {
//精确查询 =
QueryBuilder queryBuilder = QueryBuilders.termQuery("info", "abc");
//精确查询 多个 in
QueryBuilder queryBuilder1 = QueryBuilders.termsQuery("info", "abc", "asd");
//模糊匹配
QueryBuilder queryBuilder2 = QueryBuilders.matchQuery("info", "ab");
//模糊匹配 多个
QueryBuilder queryBuilder3 = QueryBuilders.multiMatchQuery("info", "ab", "tc");
//全部数据
QueryBuilder queryBuilder4 = QueryBuilders.matchAllQuery();
//多条件构建BoolQueryBuilder
BoolQueryBuilder queryBuilder5 = QueryBuilders.boolQuery();
//并且 and
queryBuilder5.must(QueryBuilders.termQuery("info", "abc"));
queryBuilder5.must(QueryBuilders.termQuery("gender", "18"));
//或者 or
queryBuilder5.should(QueryBuilders.termQuery("info", "azs"));
queryBuilder5.should(QueryBuilders.termQuery("info", "azs1"));
//不等于
queryBuilder5.mustNot(QueryBuilders.termQuery("gender", "19"));
//过滤数据
queryBuilder5.filter(QueryBuilders.matchQuery("info", "ab"));
//范围查询
/*
gt 大于 >
gte 大于等于 >=
lt 小于 <
lte 小于等于 <=
*/
queryBuilder5.filter(new RangeQueryBuilder("age").gt(10).lte(50));
//使用分词器
queryBuilder5.must(QueryBuilders.matchQuery("info","abc").analyzer("ik_max_word"));
queryBuilder5.must(QueryBuilders.matchQuery("info","abc1").analyzer("ik_smart"));
//构建分页
Pageable pageable = PageRequest.of(1, 20);
//多场景下复杂条件
SearchQuery search = new NativeSearchQueryBuilder()
.withQuery(queryBuilder4)
.withPageable(pageable)
.withSort(SortBuilders.fieldSort("age").order(SortOrder.DESC))
.build();
takeFaceRepository.search(search);
takeFaceRepository.search(queryBuilder);
takeFaceRepository.search(queryBuilder5);
//分页查询
takeFaceRepository.search(queryBuilder, pageable);
}
/*
删除
*/
@Override
public boolean delete() {
try {
//删除全部数据
takeFaceRepository.deleteAll();
//根据id
takeFaceRepository.deleteById(1L);
//根据条件
TakeEntity takeEntity = new TakeEntity();
takeEntity.setInfo("abc");
takeFaceRepository.delete(takeEntity);
return true;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
/*
修改数据,直接save保存
*/
@Override
public void update(){
TakeEntity entity = new TakeEntity();
entity.setId(10);
entity.setInfo("afg");
takeFaceRepository.save(entity);
}
}
七、Kibana基本使用
Kibana es的客户端工具,安装可参考:
https://blog.csdn.net/qq_43692950/article/details/107713161
- 创建索引
PUT /testindex
- 查询索引
GET /testindex
- 添加文档
/索引名称/类型/id
PUT /testindex/user/2
{
"name":"abc",
"sex":2,
"age":18
}
- 根据id查询文档
GET /testindex/user/1
- 查询全部
GET /testindex/_search
GET /testindex/user/_search
- 查询多个id分别为1、2
GET /testindex/user/_mget
{
"ids":["1","2"]
}
- 精确查询
GET /testindex/user/_search
{
"query": {
"term": {
"name": "abc"
}
}
}
- 模糊查询
GET /testindex/user/_search
{
"from": 1,
"size": 2,
"query": {
"match": {
"name": "abc"
}
}
}
- 删除索引
DELETE /testindex