ES倒排索引
当数据写入 ES 时,数据将会通过 分词 被切分为不同的 term,ES 将 term 与其对应的文 档列表建立一种映射关系,这种结构就是 倒排索引。如下图所示:
为了进一步提升索引的效率,ES 在 term 的基础上利用 term 的前缀或者后缀构建了 term index, 用于对 term 本身进行索引,ES 实际的索引结构如下图所示:
这样当我们去搜索某个关键词时,ES 首先根据它的前缀或者后缀迅速缩小关键词的在 term dictionary 中的范围,大大减少了磁盘IO的次数。
单词词典(Term Dictionary) :记录所有文档的单词,记录单词到倒排列表的 关联关系
常用字典数据结构:
倒排列表(Posting List)-记录了单词对应的文档结合,由倒排索引项组成
倒排索引项(Posting):
文档ID
词频TF–该单词在文档中出现的次数,用于相关性评分
位置(Position)-单词在文档中分词的位置。用于短语搜索 (match phrase query)
偏移(Offset)-记录单词的开始结束位置,实现高亮显示
Elasticsearch 的JSON文档中的每个字段,都有自己的倒排索引。
可以指定对某些字段不做索引:
优点︰节省存储空间
缺点: 字段无法被搜索
文档映射Mapping
Mapping类似数据库中的schema的定义 ,作用如下:
定义索引中的字段的名称
定义字段的数据类型,例如字符串,数字,布尔等
字段,倒排索引的相关配置(Analyzer)
ES中Mapping映射可以分为动态映射和静态映射
动态映射:
在关系数据库中,需要事先创建数据库,然后在该数据库下创建数据表,并创建表字段、类 型、长度、主键等,最后才能基于表插入数据。而Elasticsearch中不需要定义Mapping映 射(即关系型数据库的表、字段等), 在文档写入Elasticsearch时,会根据文档字段自动识 别类型,这种机制称之为动态映射。
静态映射:
静态映射是在Elasticsearch中也可以事先定义好映射,包含文档的各字段类型、分词器 等,这种方式称之为静态映射。动态映射(Dynamic Mapping)的机制,使得我们无需手动定Mappings,
Elasticsearch会自动根据文档信息,推算出字段的类型。但是有时候会推算的不对,例如地 理位置信息。 当类型如果设置不对时,会导致一些功能无法正常运行,例如Range查询
Dynamic Mapping类型自动识别:
示例
#删除原索引DELETE /user#创建文档(ES根据数据类型, 会自动创建映射)PUT /user/_doc/1{"name":"yanqiuxiang","age":34,"address":"江西南昌"}#获取文档映射GET /user/_mapping
思考:能否后期更改Mapping的字段类型?
两种情况:
新增加字段
1、 dynamic设为true时,一旦有新增字段的文档写入,Mapping 也同时被更新
2、dynamic设为false,Mapping 不会被更新,新增字段的数据 无法被索引,但是信息会出现在 _source中
3、dynamic设置成strict(严格控制策略),文档写入失败,抛出异常
对已有字段,一旦已经有数据写入,就不再支持修改字段定义
Lucene 实现的倒排索引,一旦生成后,就不允许修改
如果希望改变字段类型,可以利用 reindex API,重建索引
原因:
如果修改了字段的数据类型,会导致已被索引的数据无法被搜索
但是如果是增加新的字段,就不会有这样的影响
dynamic设置成strict,新增字段导致文档插入失败
PUT /user
{"mappings": {"dynamic": "strict","properties": {"name": {"type": "text"},"address": {"type": "object","dynamic": "true"}}}
}
修改dynamic后再次插入文档成功
#修改daynamicPUT /user/_mapping{"dynamic":true}
对已有字段的mapping修改
具体方法:
1)如果要推倒现有的映射, 你得重新建立一个静态索引
2)然后把之前索引里的数据导入到新的索引里
3)删除原创建的索引
4)为新索引起个别名, 为原索引名
PUT / user2
{"mappings": {"properties": {"name": {"type": "text"},"address": {"type": "text","analyzer": "ik_max_word"}}}
}POST _reindex
{"source": {"index": "user"},"dest": {"index": "user2"}
}DELETE /userPUT /user2/_alias/userGET /user
注意: 通过这几个步骤就实现了索引的平滑过渡,并且是零停机
常用Mapping参数配置
index: 控制当前字段是否被索引,默认为true。 如果设置为false,该字段不可被搜索
PUT /user
{"mappings": {"properties": {"address": {"type": "text","index": false},"age": {"type": "long"},"name": {"type": "text"}}}
}
有四种不同基本的index options配置,控制倒排索引记录的内容:
docs : 记录doc id
freqs:记录doc id 和term frequencies(词频)
positions: 记录doc id / term frequencies / term position
offsets: doc id / term frequencies / term posistion/character offsets