ElasticSearch是一个基于Lucene的分布式、高扩展、高实时的搜索与数据分析引擎。一般我们用来作为网站全文搜索。
为了方便理解,可以类比到关系型数据库中的概念进行对比,如下表:
关系型数据库 | Elasticsearch |
---|---|
Databases(数据库) | Indices(索引) |
Tables(表) | Types(类型) |
Rows(行) | Documents(文档) |
Columns(列) | Fields(字段) |
Elasticsearch包含多个索引(indices)(数据库),每个索引可以包含多个类型(types)(表),每个类型包含多个文档(documents)(行),每个文档包含多个字段(Fields)(列)。
<!-- es -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
<version>2.1.1.RELEASE</version>
</dependency>
windows下安装 elasticsearch
1.解压下载的压缩包
2.运行Elasticsearch 双击运行 elasticsearch-2.4.4\bin 目录下的 elasticsearch.bat 文件。
3.访问Elasticsearch浏览器访问 http://localhost:9200。(默认使用9200端口)
为便于管理Elasticsearch,安装 head 插件可实现可视化管理。
cd F:\es\elasticsearch-6.4.3\bin
elasticsearch-plugin install mobz/elasticsearch-head
访问head插件:浏览器中访问 http://localhost:9200/_plugin/head/。
es5 以上版本安装 head 需要安装 node 和 grunt(之前的直接用 plugin 命令即可安装)
1、下载安装 node
2、执行 npm install -g grunt-cli
安装 grunt ,安装完成后执行 grunt -version
查看是否安装成功,会显示安装的版本号
3、在该链接下载文件 https://github.com/mobz/elasticsearch-head/archive/master.zip
4、下载完成后解压到 elasticsearch 安装目录,使用 cmd 进入该目录下执行 npm install
, 等待安装完成…
F:\es\elasticsearch-6.4.3\elasticsearch-head-master>npm install
5、安装完成后执行 grunt server
或者 npm run start
运行 head 插件,如果不成功重新安装 grunt。
成功如下
F:\es\elasticsearch-6.4.3\elasticsearch-head-master>npm run start
> elasticsearch-head@0.0.0 start F:\es\elasticsearch-6.4.3\elasticsearch-head-master
> grunt server
Running "connect:server" (connect) task
Waiting forever...
Started connect web server on http://localhost:9100
6、访问该地址即可:http://localhost:9100
本地的 Elasticsearch 运行起来了,但生产环境每次都这样启动,未免过于麻烦且不安全。最好的方式是把 Elasticsearch 加入到 Windows 服务中(Service),每次开机自动后台启动。
打开cmd命令行:
cd F:\es\elasticsearch-6.4.3\bin
elasticsearch-service.bat install
elasticsearch-service.bat start
1、安装对应版本的 elasticsearch-analysis-ik,版本 https://github.com/medcl/elasticsearch-analysis-ik/
2、将下载的压缩包,在 plugins 文件夹下进行解压
SpirngBoot 自动完成了以下配置:
spring:
data:
elasticsearch:
#配置ElasticSearch节点名称
cluster-name: elasticsearch
#注: 9300 是 Java 客户端的端口。9200 是支持 Restful HTTP 的接口。
cluster-nodes: localhost:9300
# 使用jpa命名规范
repositories:
enabled: true
package com.manster.search.model;
import lombok.Data;
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;
import java.io.Serializable;
import java.util.Date;
/**
* @Author manster
* @Date 2022/5/20
**/
@Data
@Document(indexName = "blog", type = "blog", createIndex = true)
public class BlogDocument implements Serializable {
@Id
private Long id;
// 中文分词器
@Field(type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_smart")
private String title;
private Long authorId;
@Field(type = FieldType.Keyword)
private String authorName;
private String authorAvatar;
private Long categoryId;
@Field(type = FieldType.Keyword)
private String categoryName;
private Boolean recommend;
private Integer level;
private Integer commentCount;
private Integer viewCount;
@Field(type = FieldType.Date)
private Date created;
}
@Field(type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_smart")
表示使用 ik 分词器@Field(type = FieldType.Keyword)
表明这是一个关键字分词,不需要进行切分分词package com.manster.search.repository;
import com.manster.search.model.BlogDocument;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import org.springframework.stereotype.Repository;
/**
* @Author manster
* @Date 2022/5/20
**/
@Repository
public interface BlogRepository extends ElasticsearchRepository<BlogDocument, Long> {
}
初始化数据
//初始化上传数据
@Override
public int initEsData(List<BlogVo> records) {
if(records == null || records.isEmpty()){
return 0;
}
List<BlogDocument> documents = new ArrayList<>();
//转换对象
for (BlogVo record : records) {
BlogDocument blogDocument = new BlogDocument();
BeanUtils.copyProperties(record, blogDocument);
documents.add(blogDocument);
}
//存入es
blogRepository.saveAll(documents);
return documents.size();
}
进行查找
package com.manster.service.impl;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.manster.search.model.BlogDocument;
import com.manster.search.repository.BlogRepository;
import com.manster.service.SearchService;
import org.elasticsearch.index.query.MultiMatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
/**
* @Author manster
* @Date 2022/5/20
**/
@Service
public class SearchServiceImpl implements SearchService {
@Autowired
BlogRepository blogRepository;
@Override
public IPage search(Page page, String keyword) {
// mp 的 page 转为 jpa 的 page
Long current = page.getCurrent() - 1; //jpa中的分页从0开始
Long size = page.getSize();
Pageable pageable = PageRequest.of(current.intValue(), size.intValue());
//es 得到 page
MultiMatchQueryBuilder builder = QueryBuilders.multiMatchQuery(keyword, "title", "authorName", "categoryName");
org.springframework.data.domain.Page<BlogDocument> documents = blogRepository.search(builder, pageable);
// jpa 的 page 转为 mybatis-plus的 page
IPage pageData = new Page(page.getCurrent(), page.getSize(), documents.getTotalElements());
pageData.setRecords(documents.getContent());
return pageData;
}
}
至此我们就可以进行全局的查找了