ElasticSearch
1.1 什么是 ElasticSearch
ElasticSearch,简称为es,es是一个开源的高扩展的分布式全局检索引擎,它可以近乎实时的存储、检索数据;扩展性很好,可以扩展到上百台服务器,处理PB级别的数据。
1.1.1 什么是全局检索
1.1.1.1 数据分类
数据总体分为两种:结构化数据和非机构化数据。
- 结构化数据:指具有固定格式或有限长度的数据。如数据库,元数据
- 非结构数据:指不定长或无固定格式的数据,如邮件,word文档等磁盘上的文件
1.1.1.2 结构化数据搜索
厂家的结构化数据也就是数据库中的数据。在数据库中搜索很容易发现,通常都是使用sql语句进行查询,并且能很快的得到查询结果
为什么数据库搜索很容易
因为数据库中的数据存储是有规则的,有行有列而且数据格式、数据长度都是固定的
1.1.1.3 非结构化数据搜索
(1)顺序扫描法
所谓顺序扫描,比如要找内容包含某一个字符串的文件,就是一个文档一个文档的查看,对每个文档从头看到尾,如果此文档包含此字符,则此文档为我们要找的文件,接着看下一个文件,直到扫描完所有文件。速度很慢
(2)全文检索
将非结构化数据中的一部分信息提取出来,重新组织,使其变得有一定的结构,然后对一定的结构的数据进行搜索,从而达到搜索相对较快的目的。这部分从非结构化数据中提取出的然后重新组织的信息,我们称之索引。
这种先建立索引,再对索引进行搜索的过程就叫全文检索
虽然创建索引的过程是非常耗时的,但是索引一旦创建就可以多次使用,全文检索主要处理的是查询,索引耗时创建索引是值得的。
1.1.2 全文检索的应用场景
对于数据量大、数据结构不固定的数据可采用全文检索方式搜索,比如:百度、Google等搜索引擎、论坛站内搜索、电商网站站内搜索等。
1.1.3 全文检索的实现流程
1.1.3.1 全文检索的过程
- 索引的创建:将现实世界中所有的结构化和非结构化数据提取信息,创建索引的过程
- 搜索索引:就是得到用户的查询请求,搜索创建的索引,然后返回结构的过程
1.1.3.2 创建索引
对文档索引的过程,将用户要搜索的文档内容进行索引,索引存储在索引库(index)中。
非机构化数据中所存储的信息是每个文件中包含哪些字符串,也即已知文件,欲求字符串相对容易,也即是从问件到字符串的映射。而我们想要搜索的信息是哪些文件包含此字符,也即已知字符串,欲求文件,也即从字符串到文件的映射。两者恰恰相反。于是如果索引能够保持从字符串到文件的映射,则会大大提高索引速度。
1.1.3.3 创建文档对象
获取原始内容的目的是为了索引,在索引前需要将原始内容创建成文档(Document),文档中包括一个一个的域(FIeld),域中存储内容
操作索引 index
-
添加索引
PUT http://ip:端口/索引名称
-
查询索引
# 查询单个索引信息 GET http://ip:端口/索引名称 # 查询多个索引信息 GET http://ip:端口/索引名称1,索引名称2... # 查询全部索引信息 GET http://ip:端口/_all
-
删除索引
DELETE http://ip:端口/索引名称
-
关闭索引
POST http://ip:端口/索引名称/_close
-
开启索引
POST http://ip:端口/索引名称/_open
操作索引
# 创建索引
PUT person
# 查看索引
GET person
# 删除索引
DELETE person
# 查看映射
GET person/_mapping
# 添加映射
PUT person/_mapping
{
"properties":{
"name":{
"type":"keyword"
},
"age":{
"type":"integer"
}
}
}
# 创建索引并添加映射
PUT person
{
"mappings":{
"properties":{
"name":{
"type":"keyword"
},
"age":{
"type":"integer"
}
}
}
}
# 索引库中添加字段
PUT person/_mapping
{
"properties":{
"address":{
"type":"text"
}
}
}
操作文档 document
- 添加文档
- 查询文档
- 修改文档
- 删除文档
# 查询索引
GET person
# 添加文档,指定id
PUT person/_doc/1001
{
"name":"张三",
"age":19,
"address":"北京"
}
# 查询文档
GET person/_doc/1001
# 添加文档,不指定id(如果不指定id,会自动生成随机id)
PUT person/_doc/
{
"name":"李四",
"age":22,
"address":"上海"
}
# 查询文档
GET person/_doc/u8b2QHUBCR3n8iTZ8-Vk
# 查询所有文档
GET person/_search
# 删除文档
DELETE person/_doc/1
# 修改文档 根据id,id存在就是修改,id不存在就是添加
PUT person/_doc/1
{
"name":"王五",
"age":32,
"address":"深圳"
}
全文查询 -match查询
# 添加一些文档
PUT person/_doc/1002
{
"name":"fwj",
"age":20,
"address":"河南焦作"
}
PUT person/_doc/1003
{
"name":"lxy",
"age":22,
"address":"河南南阳"
}
PUT person/_doc/1002
{
"name":"gyx",
"age":20,
"address":"河南洛阳"
}
# 查询全部文档
GET person/_search
# 进行 match 查询
# 先会对查询的字符串进行分词,再查询,求交集
GET person/_search
{
"query":{
"match":{
"address":"河南"
}
}
}
# 进行 term 查询
# 词条查询不会分析条件,只有当词条和查询字符串完全匹配时才匹配搜索
GET person/_search
{
"query":{
"term":{
"address":{
"value"="河"
}
}
}
}
# 关键字搜索数据
GET person/_search?q=name:李四
DSL 查询
由ES提供丰富且灵活的查询语言叫做DSL查询(Query DSL),它允许你构建更加复杂、强大的查询。
DSL(Domain Specific Language特定领域语言)以JSON请求体的形式出现。
# 根据年龄查询
POST person/_search
{
"query":{
"match":{
"age":20
}
}
}
# 查询年龄大于20,并且地址在陕西的
POST student/_search
{
"query":{
"bool":{
"filter":{
"range":{
"age":{
"gt":20
}
}
}
},
"must":{
"match":{
"address":"陕西"
}
}
}
}
# 全文搜索
GET student/_search
{
"query":{
"match":{
"name":"张三 李四"
}
}
}
高亮显示
GET student/_search
{
"query":{
"match":{
"name":"张三"
}
},
"hightlight":{
"fields":{
"name":{}
}
}
}
聚合
类似 sql 中的 group by 操作
GET student/_search
{
"aggs":{
"all_interests":{
"terms":{
"field":"name"
}
}
}
}
指定相应字段
GET student/_search?_source=name,age
GET student/_doc/1001?_source=name,age
判断文档是否存在
HEAD student/_doc/1002
批量操作
有些情况可以通过批量操作减少网络请求。如:批量查询,批量插入数据
批量查询(只支持 id 查询)
POT student/_mget
{
"ids":["1001","1002"]
}
_bulk 操作
es 中,支持批量的插入、删除、修改,都是通过 _buld 的 api 完成
批量插入
POST _bulk
{"create":{"_index":"student","_id":2001}}
{"id":2001,"name":"name1","age":33,"address":"北京"}
{"create":{"_index":"student","_id":2002}}
{"id":2002,"name":"name2","age":23,"address":"佛山"}
批量修改
POST _bulk
{"update":{"_index":"student","_id":2001}}
{"doc":{"id":2001,"name":"name11","age":111,"address":"北京朝阳"}}
{"update":{"_index":"student","_id":2002}}
{"doc":{"id":2002,"name":"name22","age":222,"address":"佛山无影脚"}}
批量删除
POST _bulk
{"delete":{"_index":"student","_id":2001}}
{"delete":{"_index":"student","_id":2002}}
分页
size:结果数,默认10
from:跳过开始的结果数,默认0
GET /_search?size=5
GET /_serach?size=5&from=2
GET studemt/_search?size=3&from=1
terms 查询
terms 跟 term 类似,但 terms 允许指定多个匹配条件
POST student/_search
{
"query":{
"terms":{
"age":[20,21]
}
}
}
range 查询
范围
exists 查询
存在 ,类似 is_null
ik 分词器
标准分词器,一个字一个字进行分词
POST _analyze
{
"text":"你好啊,北京"
}
standard 标准分词,按单词切分,并且会转化成小写
POST _analyze
{
"analyze":"standard",
"text":"I am a student"
}
ik 分词器插件
ik 提供了两种算法 ik_smart 和 ik_max_word
ik_smart 为最少切分,ik_max_word 为最细粒度划分
# ik_smart
POST _analyze
{
"analyze":"ik_smart",
"text":"我是程序员"
}
# 将会划分为 我、是、程序员
# ik_max_word
POST analyze
{
"analyze":"ik_max_word",
"text":"我是程序员"
}
# 讲会划分为 我、是、程序员、程序
创建索引时使用分词器 ik_max_word
PUT student
{
"mappings":{
"properties":{
"name":{
"type":"keyword"
},
"address":{
"type":"text",
"anaryze":"ik_max_word"
}
}
}
}
添加文档
PUT student1/_doc/1{
"name":"tom",
"address":"深圳宝安"
}
PUT student1/_doc/2{
"name":"jack",
"address":"深圳福田"
}
PUT student1/_doc/3{
"name":"tom",
"address":"华为5G"
}
term 查询
GET sutdent1/_search
{
"query":{
"term""{
"address":{
"value":"深圳"
}
}
}
}