一、ES核心概念
1,倒排索引
Elasticsearch使用的是一种称为倒排索引的结构,采用Lucene倒排索引作为底层。这种结构适用于快速的全文检索,一个索引由文档中所有不重复的列表构成,对于每一个词,都有一个包含它的文档列表。
实例:
对以下三个文档构造倒排索引。
倒排索引-组成
- 单词词典(Term Dictionary)
- 倒排列表(Posting List)
ES存储的是一个JSON格式的文档,其中包含多个字段,每个字段会有自己的倒排索引。
倒排索引的结构
- 包含这个关键词的document list
- 包含这个关键词的所有document的数量:IDF(inverse document frequency)
- 这个关键词在每个document中出现的次数:TF(term frequency)
- 这个关键词在这个document中的次序
- 每个document的长度:length norm
- 包含这个关键词的所有document的平均长度
倒排索引不可变的好处
- 不需要锁,提升并发能力,避免锁的问题
- 数据不变,一直保存在os cache中,只要cache内存足够
- filter cache一直驻留在内存,因为数据不变
- 可以压缩,节省cpu和io开销
2,分词
analysis——文本分析是把全文转换成一系列单词(term/token)的过程,也叫分词
analysis是通过Analyzer来实现的。可使用Elasticsearch内置的分析器/或者定制化分析器。
使用_analyzer API
GET _analyze
{
"analyzer":"ik_smart",
"text":"我是一名Java开发工程师"
}
# analyzer:指定哪种分词器
# text: 要测试的文本
默认的es分词器对中文的分词不友好,我们会使用插件,ik分词器。
安装ik分词器步骤
官网下载路径是在githup上:https://github.com/medcl/elasticsearch-analysis-ik
- 官网下载的ik分词器的版本要与ES的版本一致
- 下载的zip文件解压后放到plugins下新建的一个ik文件夹下面
- 在plugins路径下,终端使用ls -a命令查看
- 删除.DS_Store文件
- 重启es即可
3,匹配度
在es查询结果中, 有一个‘_score’字段,这个是匹配度分数的意思。分数越高,结果越靠前。
由ES打分算法得出来的。
二、Rest风格的执行命令
1,字段类型
(核心基础类型,还有其他复杂类型)
字符串类型:text,keyword
数字类型:long,integer,short,byte,double,float,half_float,scaled_float
日期类型:date
布尔类型:boolean
二进制类型:binary
2,创建一个索引
创建索引并指定mapper
# demotest 是索引名称
# settings 设置了主分片和副本的数量
# mappings 是映射字段,_doc是索引类型,可以自定义命名
# 注意点,本语法是在7.14.1版本,因此要使用‘include_type_name=true’
# 其实,没有特殊要求,mappings可以不用设置,插入数据时会自动创建
PUT /demotest?include_type_name=true
{
"settings": {
"number_of_replicas": 1,
"number_of_shards": 2
},
"mappings": {
"_doc": {
"properties": {
"name": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"age": {
"type": "integer"
},
"sex": {
"type": "text"
}
}
}
}
}
3,新增一条文档
# 指定id的方式添加
PUT demotest/_doc/1
{
"name": "张三",
"age": "16",
"sex": "man"
}
# 不指定id的方法添加,id会自动生成
POST demotest/_doc
{
"name": "李四",
"age": "17",
"sex": "man"
}
4,修改一条文档
# 方式一,和添加一条文档命名一样,当id存在,则是更新了
PUT demotest/_doc/1
{
"name": "李四",
"age": "19",
"sex": "man"
}
# 方式二、使用POST加_update方式,注意需要一个doc包裹更新的字段
POST demotest/_doc/1/_update
{
"doc": {
"sex": "woman"
}
}
# 两者的区别,PUT方式修改的话,如果某个字段不传,那么这条数据的字段就被替换为空
# 所以修改操作使用POST的方式更好
5,删除一条文档
# 指定索引和id的方式删除
DELETE demotest/_doc/1
6,查看所有文档
# 更多查询的操作后面详解
GET demotest/_search
三、关于文档的基本操作
# 1,基础查询
GET demotest/_search
{
"query": {
"match": {
"sex": "man"
}
}
}
# 2,排序,sort
GET demotest/_search
{
"query": {
"match": {
"sex": "man"
}
},
"sort": [
{
"age": {
"order": "desc"
}
}
]
}
# 3,分页查询,from:第几个,size:返回多少条
GET demotest/_search
{
"query": {
"match": {
"sex": "man"
}
},
"sort": [
{
"age": {
"order": "desc"
}
}
],
"from": 0,
"size": 2
}
# 4,只返回指定的字段数据
GET demotest/_search
{
"query": {
"match": {
"sex": "man"
}
},
"_source": [
"name",
"age"
]
}
# 5,bool查询,有must,must_not,should,filter
# must是and条件查询,must_not是过滤,也是and条件
# should是or条件查询
# filter是过滤查询,也是and条件
# 区别:filter不计算评分,查询效率高;有缓存
GET demotest/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"age": "36"
}
},
{
"match": {
"sex": "man"
}
}
]
}
}
}
# 6,term 查询是直接通过倒排索引指定的词条进行精确查找的
GET demotest/_search
{
"query": {
"term": {
"sex": "man"
}
}
}
关于分词:
term:直接查询精确的
match:会使用分词器解析
两个类型 text keyword
text:可以被分词器解析
keyword:不被分词器解析,以完整的词存储
如果字段类型是text,那么可以使用match,根据分词器解析来查询到数据。但是要完全匹配一个字段的值,则可能会查不到。
如果字段类型是keyword,那么可以使用term来精确查找。因为keyword不分词,以完整词存储。
因此更多实际场景,有些字段的类型会是text和keyword两者都具备,这是可以的。
字段类型设置如下图:
text类型的:
比如desc字段,一般使用match查询匹配,类似模糊搜索。若是使用term精确查询,则可能会差不到。
keyword类型的:
比如sex字段,term和match都可以,但值要和数据库已有的准确匹配到才能匹配出来。
text和keyword类型都具备的:
比如name字段,这时候如果要模糊匹配,则使用match查找,若要精确匹配name字段的值,则使用name.keyword当字段查询。
GET demotest5/_search
{
"query": {
"term": {
"name.keyword": "刘备"
}
}
}
这个其实理解倒排索引原理就很容易知道这两个类型的意思了。
高亮显示:highlight
GET demotest/_search
{
"query": {
"match": {
"like": "羽毛球"
}
},
"highlight": {
"pre_tags": "<p class='key' style='color:red'>",
"post_tags": "</p>",
"fields": {
"like": {}
}
}
}