目录
Elasticsearch 1: 基本原理和概念
Elasticsearch 2: 管理索引和文档
Elasticsearch 3: 数据检索和分析
Elasticsearch 4: 相关性检索和组合查询
Elasticsearch 5: 聚集查询
Elasticsearch 6: 索引别名
Elasticsearch 集群
SpringBoot 整合 Elasticsearch
1. 倒排索引 Inverted index
- 将文档中包含的关键字全部提取处理,然后再将关键字和文档之间的对应关系保存起来,最后再对关键字本身做索引排序。用户在检索某一个关键字时,先对关键字的索引进行查找,再通过关键字与文档的对应关系找到所在文档。
- 在存储在关系型数据库中的数据,需要我们事先分析将数据拆分为不同的字段,而在 es 这类的存储中,需要应用程序根据规则自动提取关键字,并形成对应关系。
- 这些预先提取的关键字,在全文检索领域一般被称为 term(词项),文档的词项提取在 es 中被称为文档分析,这是全文检索很核心的过程,必须要区分哪些是词项,哪些不是,比如很多场景下,apple 和 apples 是同一个东西,望和看其实是同一个动作。
- 比如现在有:
蜀道难(唐)李白 蜀道之难难于上青天,侧身西望长咨嗟。
静夜思(唐)李白 举头望明月,低头思故乡。
春台望(唐)李隆基 暇景属三春,高台聊四望。
鹤冲天(宋)柳永 黄金榜上,偶失龙头望。明代暂遗贤,如何向?未遂风云便,争不恣狂荡。何须论得丧?才子词人,自是白衣卿相。烟花巷陌,依约丹青屏障。幸有意中人,堪寻访。且恁偎红翠,风流事,平生畅。青春都一饷。忍把浮名,换了浅斟低唱! - 都有望字,于是我们可以这么保存
- 如果查哪个诗词中包含上,怎么办,上述的表格可以继续填入新的记录
- 上述诗词的中每个字都可以作为关键字,然后建立关键字和文档之间的对应关系,也就是标识关键字被哪些文档包含。
2. 基本概念
- 比较关键的基本概念有索引、文档、映射、映射类型、文档字段概念,为了方便理解,可以和关系数据库中的相关概念进行个比对
这里的映射类型在es7之后,就只保留一种类型为_doc,相当于在数据库中只存在一张表
3. Elasticsearch索引
- Elasticsearch 索引是映射类型的容器。一个 Elasticsearch 索引非常像关系型世界的数据库,是独立的大量文档集合。
最基本的结构就是“keyword”和“PostingList”,Posting list 就是一个 int 的数组,存储了所有符合某个 term 的文档 id。 - 它会保存每一个词项出现过的文档总数, 在对应的文档中一个具体词项出现的总次数,词项在文档中的顺序,每个文档的长度,所有文档的平均长度等相关信息。
4. 文档 (Document)
- 文档是 es 中所有可搜索数据的最小单位,比如日志文件中的日志项、一部电影的具体信息等等。
- 文档会被序列化 JSON 格式保存到 ElasticSearch 中,JSON 对象由字段组成,每个字段都有对象的字段类型(字符串,数值,布尔,日期,二进制,范围类型)。同时每个文档都有一个 Unique ID,可以自己指定 ID,或者通过 ElasticSearch 自动生成。
- 所以严格来说,es 中存储的文档是一种半结构化的数据。
5. 映射
- 映射(mapping)定义了每个字段的类型、字段所使用的分词器等。
- 可以显式映射,由我们在索引映射中进行预先定义;也可以动态映射,在添加文档的时候,由 es 自动添加到索引,这个过程不需要事先在索引进行字段数据类型匹配等等,es 会自己推断数据类型。
6. 文档字段
- 文档中的一个字段 field 就相当于关系型数据库中的一列 column,那么它肯定有数据类型,es 提供的数据类型包括至少有:
6.1 数据类型
6.1.1 核心数据类型
- 字符串类型: string,字符串类还可被分为 text 和 keyword 类型,如果我们让 es 自动映射数据,那么 es 会把字符串定义为 text,并且还加了一个 keyword类型字段。
text 文本数据类型,用于索引全文值的字段。使用文本数据类型的字段,它们会被分词,在索引之前将字符串转换为单个术语的列表(倒排索引),分词过程允许 ES 搜索每个全文字段中的单个单词。什么情况适合使用 text,只要不具备唯一性的字符串一般都可以使用 text。
keyword,关键字数据类型,用于索引结构化内容的字段。使用 keyword 类型的字段,其不会被分析,给什么值就原封不动地按照这个值索引,所以关键字字段只能按其确切值进行搜索。什么情况下使用 keyword,具有唯一性的字符串,例如:电子邮件地址、MAC 地址、身份证号、状态代码…等等。 - 数字型数据类型:long、integer、short、byte、double、float
- 日期类型:date
- 布尔类型:boolean
6.1.2 复杂数据类型
- 数组:无需专门的数据类型
- 对象数据类型:单独的 JSON 对象
- 嵌套数据类型:nested,关于 JSON 对象的数组
6.1.3 地理数据类型
- 地理点数据类型
- 地理形状数据类型
6.1.4 专门数据类型
- IPv4 数据类型
- 单词计数数据类型 token_count
6.2 数组
- 不需要特殊配置,一个字段如果被配置为基本数据类型,就是天生支持数组类型的。任何字段都可以有 0 个或多个值,但是在一个数组中数据类型必须一样。
put /open-soft/_doc/2
{
"name": [
"Apache Activemq",
"Activemq Artemis"
],
"lang": "Java",
"corp": "Apache",
"stars": [
500,
200
]
}
6.3 对象
- JSON 文档是有层次结构的,一个文档可能包含其他文档,如果一个文档包含其他文档,那么该文档值是对象类型,其数据类型是对象。当然 ElasticSearch中是没有所谓对象类型的,比如:
put /open-soft/_doc/3
{
"name": [
"Apache ShardingSphere"
],
"lang": "Java",
"corp": "JingDong",
"stars": 400,
"address": {
"city": "BeiJing",
"country": "亦庄"
}
}
- 对象类型可以在定义索引的映射关系时进行指定。
6.4 多数据类型
- 如果说数组允许你使用同一个设置索引多项数据,那么多数据类型允许使用不同的设置,对同一项数据索引多次。带来的好处就是可以同一文本有多种不同的索引方式,比如一个字符串类型的字段,可以使用 text 类型做全文检索,使用keyword 类型做聚合和排序。我们可以看到 es 的动态映射生成的字段类型里,往往字符串类型都使用了多数据类型。当然,我们一样也可以自己定义:
put /open-soft/_mapping
{
"properties": {
"name": {
"type": "text",
"fields": {
"raw": {
"type": "keyword"
},
"length": {
"type": "token_count",
"analyzer": "standard"
}
}
}
}
}
- 在上面的代码里,我们使用"fields"就把 name 字段扩充为多字段类型,为name 新增了两个子字段 raw 和 length,raw 设置类型为 keyword,length 设置类型为 token_count,告诉 es 这个字段在保存还需要做词频统计。
- 通过 fields 字段设置的子字段 raw 和 length,在我们添加文档时,并不需要单独设置值,他们 name 共享相同的值,只是 es 会以不同的方式处理字段值。同样在检索文档的时候,它们也不会显示在结果中,所以它们一般都是在检索中以查询条件的形式出现,以减少检索时的性能开销。
7. 字段参数
7.1 analyzer
- 指定分词器。elasticsearch 是一款支持全文检索的分布式存储系统,对于 text类型的字段,首先会使用分词器进行分词,然后将分词后的词根一个一个存储在倒排索引中,后续查询主要是针对词根的搜索。
- analyzer 该参数可以在每个查询、每个字段、每个索引中使用,其优先级如下(越靠前越优先):
1、字段上定义的分词器
2、索引配置中定义的分词器
3、默认分词器(standard)
7.2 fields
- fields 可以让同一文本有多种不同的索引方式,比如一个 String 类型的字段,可以使用 text 类型做全文检索,也可以使用 keyword 类型做聚合和排序。
7.3 properties
- Object 或者 nested 类型,下面还有嵌套类型,可以通过 properties 参数指定。
比如:
PUT my_index
{
"mappings": {
"my_type": {
"properties": {
"manager": {
"properties": {
"age": {
"type": "integer"
},
"name": {
"type": "text"
}
}
},
"employees": {
"type": "nested",
"properties": {
"age": {
"type": "integer"
},
"name": {
"type": "text"
}
}
}
}
}
}
}
- 对应的文档结构
PUT my_index/my_type/1
{
"region": "US",
"manager": {
"name": "Alice White",
"age": 30
},
"employees": [
{
"name": "John Smith",
"age": 34
},
{
"name": "Peter Brown",
"age": 26
}
]
}
7.4 ignore_above
- ignore_above 用于指定字段索引和存储的长度最大值,超过最大值的会被忽略。这是索引在静态设置中唯一能修改的参数。
8. 元字段 meta-fields
- 一个文档根据我们定义的业务字段保存有数据之外,它还包含了元数据字段(meta-fields)。元字段不需要用户定义,在任一文档中都存在,有点类似于数据库的表结构数据。在名称上有个显著的特征,都是以下划线“_”开头。
- 大体分为五种类型:身份(标识)元数据、索引元数据、文档元数据、路由元数据以及其他类型的元数据,当然不是每个文档这些元字段都有的。
8.1 身份(标识)元数据
- _index:文档所属索引 , 自动被索引,可被查询,聚合,排序使用,或者脚本里访问
- _type:文档所属类型,自动被索引,可被查询,聚合,排序使用,或者脚本里访问
- _id:文档的唯一标识,建索引时候传入 ,不被索引,可通过_uid 被查询,脚本里使用,不能参与聚合或排序
- _uid:由_type 和_id 字段组成,自动被索引 ,可被查询,聚合,排序使用,或者脚本里访问,6.0.0 版本后已废止。
8.2 索引元数据
- _all: 自动组合所有的字段值,以空格分割,可以指定分器词索引,但是整个值不被存储,所以此字段仅仅能被搜索,不能获取到具体的值。6.0.0 版本后已废止。
- _field_names:索引了每个字段的名字,可以包含 null 值,可以通过 exists查询或 missing 查询方法来校验特定的字段
8.3 文档元数据
- _source : 一个 doc 的原生的 json 数据,不会被索引,用于获取提取字段值 ,启动此字段,索引体积会变大,如果既想使用此字段又想兼顾索引体积,可以开启索引压缩。
- _source 是可以被禁用的,不过禁用之后部分功能不再支持,这些功能包括:
部分 update api、运行时高亮搜索结果
索引重建、修改 mapping 以及分词、索引升级
debug 查询或者聚合语句
索引自动修复 - _size: 整个_source 字段的字节数大小,需要单独安装一个 mapper-size 插
件才能展示。
8.4 路由元数据
- _routing: 一个 doc 可以被路由到指定的 shard 上。
8.5 其他
- _meta:一般用来存储应用相关的元信息。
例如:
put /open-soft/_mapping
{
"_meta": {
"class": "cn.enjoyedu.User",
"version": {
"min": "1.0",
"max": "1.3"
}
}
}