ElasticSearch全文搜索引擎
1. 全文搜索ES入门
1.1 全文搜索的概念:
将无结构化的数据转换成有结构话的数据,来加快对文本的快速搜索。
如下面所述:有序数组是一种常用的数据存储容器;红黑树等这类算法则被广泛应用于构建具有较高查询效率的数据结构;它们均基于组织化数据模型的设计原理
1.2 常见的全文搜索
1.Lucene
2.Elastic Search(ES)
3.Solr
1.3 全文搜索与like的区别
like:将关键字与数据库中的数据进行 一个个 比对,效率低下
对数据进行分词处理后,接着对结果进行排序及去重操作;随后生成数据及其对应的编号用于构建索引区域。
原数据作为数据区;
索引库:索引区+数据区
搜索的原理:系统会利用二分查找来检索数据,在索引区查找相关信息并确定对应编号后,在数据区进行精确匹配以获取完整信息以提高搜索速度。

2. ElasticSearch概述和安装
2.1 ES与Lucene的区别
1.ES支持分布式和集群
2.ES操作更简单
3.Lucene只支持java,而ES支持多种语言
2.2 ES的安装
在线地址:
安装步骤(适用windows系统):
1.选择ES合适的版本号,下载其ES的压缩包
2、直接解压到指定的文件夹
3.找到其bin目录下的elasticsearch.bat,双击即可启动ES服务器
4.验证ES服务器是否成功启动:
使用浏览器访问:http://localhost:9200 ,如果能成功访问,则启动成功。
2.3 ES的配置
可以修改 jvm.options 文件来修改内存;

2.4 Kibana5安装
Kibana5:这个相当于是ES的可视化界面(客户端操作服务器)
下载地址:https://www.elastic.co/downloads/kibana
2.4.1 Kibana5的安装与启动
解压即可安装 , 执行bin\kibana.bat 即可启动Kibana
2.4.2 Kibana5的配置
编辑config/kibana.yml,设置elasticsearch.url的值为已启动的ES
注意:通常情况下,默认会连接本地的默认Elasticsearch实例http://localhost:9200;如果要更改连接到Elasticsearch服务器的地址,在安装目录下的config/kibana.yml中取消注释指定对应的配置项#elasticsearch.url: "http://localhost:9200"即可完成设置。
2.4.3 测试Kibana
浏览器访问 http://localhost:5601 --Kibana默认地址
3. ElasticSearch的基本使用
3.1 通过Kibana去操作ElasticSearch
访问Kibana成功后,点击Dev Tools(开发者工具)

3.2 索引库基本CRUD操作
3.2.1 进行CRUD之前的补充:
| ElastciSearch全文搜索 | Mysql关系型数据库 |
|---|---|
| 索引库(index) | 数据库(database) |
| 文档类型(Type) | 数据表(Table) |
| 文档(Document) | 一行数据(Row) |
| 字段(field) | 一个列(column) |
| 文档ID | 主键ID |
| 查询(Query DSL) | 查询(SQL) |
| GET http://.. | SELECT * FROM ... |
| PUT http:// | UPDATE table set... |
3.2.2 索引库基本CRUD操作
- 查询所有的索引库
操作指令:GET _cat/indices?v

- 查看指定索引库
GET _cat/indices/索引库名

- 删除索引库
DELETE 索引库名

- 创建索引文档
PUT 索引库/文档类型/文档id
{
JSON格式,文档原始数据
}

- 获取索引库中指定文档
GET 索引库/类型/文档ID

修改索引库指定的文档
(一)(这里是修改文档id为4的文档数据)

注意:这是 全局修改,当前修改数据会覆盖原来的数据
(二)

此操作属于局部调整范围之内,在此过程中仅限于替换相关数据项而不影响其他信息存储
3.3文档简单的查询
- 查询所有
GET _search

- 查询指定的索引库
GET 索引库名/_search

- 查询索引库中指定类型的数据
GET 索引库名/user/_search

- 查询指定文档
GET 索引库名/user/11

3.4 DSL查询与过滤
3.4.1综合案例
根据用户名(name)筛选出包含"zs"的用户记录,在性别(sex)为男性(1)的情况下,并且仅限于年龄(age)在18至20岁之间的用户群体中进行数据检索;要求按照用户的年龄值(age)降序排列结果;限定返回第一页的前十项数据
GET /aigou/product/_search
{
"query":{
"bool": {
"must": [{
"match": {
"name": "zs"
}
}],
"filter": [
{
"range":{ //范围查询
"age":{
"gte":18,
"lte":20
}
}
},
{
"term": { //词元查询
"sex": 1
}
}
]
}
},
"from": 1,
"size": 10,
"_source": ["id", "name", "age","username"],
"sort": [{
"age": "desc"
}]
}
备注:
query : 查询,所有的查询条件在query里面
布尔值 : 它允许将多种查询条件聚合在一起作为单一的查询对象;这里实现了 DSL 查询功能以及过滤机制。
must : 必须匹配 :与(must) 或(should) 非(must_not)
match:分词匹配查询,会对查询条件分词 , multi_match :多字段匹配
filter: 过滤条件
term:词元查询,不会对查询条件分词
from,size :分页
_source :查询结果中需要哪些列
sort:排序
3.4.2 匹配搜索与过滤(prefix)
{
"query": {
"prefix": {
"fullName": "王"
}
}
}
3.4.3 通配符搜索(wildcard)
{
"query": {
"wildcard": {
"fullName": "倪*华"
}
}
}
3.5 分词器安装和使用
ES对英文文本的分词功能配置较为完善。然而,在进行中文全文检索操作时,则必须搭配相应的中文分词器配合使用;如同Lucas的一般做法是,在执行中文全文检索之前,应先集成IKBOW中的汉化处理机制以确保数据完整性 - 大家都在用IKBOW
3.5.1 下载地址:
this application, known as GitHub - medcl/elasticsearch-analysis-ik, incorporates the Lucene IK analyzer within the Elasticsearch platform and offers the flexibility to customize dictionaries.
3.5.2 解压elasticsearch-analysis-ik-5.2.2.zip文件
并将解压后的内容放置于ES根目录/plugins/ik
3.6文档类型映射
3.6.1 文档类型介绍
字符串类型:text(添加数据的时候分词)/keyword(添加数据的时候不分词)
数字类型:long、integer、short、double
日期类型:date
逻辑类型 :boolean
3.6.2 添加映射
注意:先创建索引库,再添加映射,最后在添加文档数据
1.实操
#查看当前索引库的类型的映射
GET /order/_doc/_mapping
#创建索引库
PUT /pet
#添加映射
PUT /pet/_doc/_mapping
{
"_doc": {
"properties": {
"id": {
"type": "long"
},
"name": {
"type": "keyword"
},
"title": {
"type": "text",
"analyzer": "ik_smart",
"search_analyzer": "ik_smart"
},
"age": {
"type": "integer"
},
"sex": {
"type": "integer"
}
}
}
}
2.补充
分析器:生成用于构建索引的分词工具(如ik_smart、ik_max_word以及standard等)。
search_analyzer:搜索分析器:当在该字段的数据中进行查询时,传入的查询内容会被解析为关键词集合。
4. Springboot整合ElasticSearch实操
4.1导入依赖
<!--SpringBoot-->
<parent>
<groupId> org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.5.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
4.2 手动配置resources下的yml文件
spring:
elasticsearch:
rest:
uris: http://localhost:9200
4.3 自动配置启动类
@SpringBootApplication
public class App
{
public static void main( String[] args )
{
SpringApplication.run(App.class,args);
}
}
4.4 创建实体类(对应ES中的索引库的类型和字段)
//文档注解 ,indexName--索引库的名字,type--文档类型
@Document(indexName = "order", type = "_doc")
@Data
public class OrderDto {
//@Id--标记该文档id为该实体类的id
@Id
private Long id;
//@Field--文档的字段;FieldType--文档字段的类型
@Field(type = FieldType.Integer)
private Integer count;
@Field(type = FieldType.Date)
private Date createTime;
//analyzer--添加字符串的的时候分词,searchAnalyzer查询的时候分词
@Field(type = FieldType.Text, analyzer = "ik_smart", searchAnalyzer = "ik_smart")
private String title;
@Field(type = FieldType.Keyword)
private String name;
@Field(type = FieldType.Double)
private BigDecimal price;
}
4.5 写一个接口继承ElasticsearchRepository接口
@Repository
public interface ESRepository extends ElasticsearchRepository<OrderDto,Long> {
}
4.6 测试
@RunWith(SpringRunner.class)
@SpringBootTest(classes = App.class)
public class esTest {
//依赖注入ESRepository,这是继承ElasticsearchRepository接口的子接口,用来做CRUD的
@Autowired
private ESRepository esRepository;
//Elasticsearch自带的,用来创建索引库和添加映射的
@Autowired
private ElasticsearchRestTemplate template;
@Test
public void test01() throws Exception{
//创建索引
template.createIndex(OrderDto.class);
//添加映射
template.putMapping(OrderDto.class);
}
@Test
public void test02() throws Exception{
//添加数据到索引库
OrderDto orderDto = new OrderDto();
for (int i =2;i<10;i++){
orderDto.setId(new Long(i));
orderDto.setCount(10+i);
orderDto.setName("宠物"+i);
orderDto.setTitle("雪山幼犬"+i);
orderDto.setPrice(new BigDecimal(20*i));
orderDto.setCreateTime(new Date());
esRepository.save(orderDto);
}
}
//通过文档id去查指定数据
@Test
public void test03() throws Exception{
//通过文档id去查指定数据
Optional<OrderDto> optional = esRepository.findById(3L);
//获取数据,并打印
OrderDto orderDto = optional.get();
System.out.println(orderDto);
}
//查询该索引库的所有数据
@Test
public void test04() throws Exception{
//查询该索引库的所有数据
Iterable<OrderDto> iterable = esRepository.findAll();
//遍历所有数据
for (OrderDto orderDto : iterable) {
System.out.println(orderDto);
}
}
@Test
public void test05() throws Exception{
//通过文档id删除某条数据
// esRepository.deleteById(1L)
Optional<OrderDto> orderDto = esRepository.findById(3L);
OrderDto orderDto1 = orderDto.get();
System.out.println(orderDto1);
//通过传入该对象,删除索引库对应的数据
esRepository.delete(orderDto1);
}
//局部修改是先传id和修改的属性
//全局修改是先查询西湖来,再进行修改
@Test
public void test06() throws Exception{
// Optional<OrderDto> orderDto = esRepository.findById(4L);
// OrderDto orderDto1 = orderDto.get();
// System.out.println(orderDto1);
OrderDto orderDto = new OrderDto();
orderDto.setId(4L);
orderDto.setName("888hhh");
esRepository.save(orderDto);
}
}
