ElasticSearch 基础

384 阅读4分钟
Document 元数据

image-20210713104050151.png

index 相当于传统数据库的 database,类似于上图中的 Goods 其中就包含了所有的商品。

type 相当于传统数据库的 table,商品中可能包含电子产品和食品。

document 是 es 存储数据的基本单位,相当于传统数据库的行数据。

field 是数据的域,相当于属性。不同 typedocument ,他们的域类似,但不完全相同。比如食品比电子产品多了一个保质期的 field

_id 便是 document 的唯一标识,在 index 和 type 下唯一,可以自定义也可以自动生成。

CRUD
document 创建与替换

document 的创建和更新都是通过唯一标识 _id 来判断。

PUT /_index/_type/_id

如果 _id 不存在,那么就是创建;反之,就是更新

document 是不可变的,如果要更新其中的内容,第一种方式就是全量替换,直接对 document 重新建立索引,替换其中所有的内容。被替换的 document 不会被立刻删除,而是被 es 标记成 deleted ,es 会在适当的时机自动删除被标记的 document

因为创建和更新的语法都是相同的,那么如果此时我们仅需要创建一个 document ,在已经存在的情况下也不需要替换,那么我们可以选择使用 _create 指定不需要覆盖。

PUT /_index/_type/_id/_create
partial update

同理,如果只需要更新不需要创建,则可以使用第二种方式,使用 _update 进行 partial update 指定不需要创建。

PUT /_index/_type/_id/_update

partial update 原理与全量替换基本一致:

但是只需要传递部分的 field 到 es,es 会在内部获取 document,然后替换掉被更新的 field,最后将新的 document创建出来,并将被替换的 document 标记为 deleted

partial update 将所有的操作都聚集在同一个 shard 内部,既减少了网络传输的开销,又减少了查询与修改的时间间隔,可以有效减少并发冲突。

document 删除
DELECT /_index/_type/_id
bulk 批量增删改 API
POST /_index/_bulk
{"action": {"meta"}}\n
{"data"}\n
{"action": {"meta"}}\n
{"data"}\n

为什么 bulk 要使用这样奇特的 json 格式?

bulk 中的每个操作可能要转发到不同的 nodeshard 中执行。所以请求到达 es 后,如果采用标准的 json 格式,es 则需要花耗费更多的开销来将其解析成对象用于分离,还会增加 jvm gc 的开销。

使用这种格式的 json,无需将其转换成 json 对象,直接按照换行符切割,两行一组。然后读取 meta,进行 document 路由,直接将 json 发送到 node 上。

document 检索
GET /_index/_type/_id
分页
GET /_search?size=10&from=0

分布式分页需要使用协调节点来聚合并返回结果,请避免使用 deep paging,否则会带来严重的性能问题。

multi-index/type
GET /_index1,index2/type1,type2/_search
Query DSL
GET /_index/_type/_search
{
	"query": {
		"match_all": {}
	}
}
mget 批量查询 API

不同 index:

GET /_mget
{
	"docs": [
		{
			"_index": "index1",
			"_type": "type",
			"_id": 10
		},
		{
			"_index": "index2",
			"_type": "type",
			"_id": 10
		}
	]
}

相同 index:

GET /_index/_type/_mget
{
	"ids": [10, 11]
}
mapping

就是 indextype 元数据,每个 type 都有一个自己的 mapping,决定了数据类型,建立倒排索引的行为,还有进行搜索的行为。

对于不同的数据类型,可能是 exact value,也可能是 full text

exact value,在建立倒排索引的时候,分词的时候,是将整个值一起作为一个关键词建立到倒排索引中的;

full text,会经历各种各样的处理,分词,normalization,之后才建立到倒排索引中。

normalization:时态转换、同义词转换、大小写转换等

对以上两种类型搜索的行为也是不一样的,exact value 会按照整个值进行匹配;full text 则会进行分词和 normalization 再去倒排索引中匹配。

 filter 与 query

filter:根据搜索条件进行过滤,不需要计算得分

query:会计算每个 document 相对于搜索条件的相关度,然后按照相关度排序

排序

由于 es 需要对数据进行分词处理建立倒排索引,进行排序时结果可能不准确。

通常的解决方案是,建立两个索引,倒排索引用于查询,正排索引用于排序。

scroll 技术滚动搜索大量数据

如果一次性要查出来数万条数据,那么性能会很差,此时一般会采用 scoll 滚动查询,分批查询,直到所有查询都处理完。

scroll 搜索会在第一次搜索的时候,保存一个当时的视图快照,之后只会基于该旧的视图快照提供数据搜索,如果这个期间数据变更,是不会让用户看到的。

每次发送 scroll 请求,我们还需要指定一个 scroll 参数,指定一个时间窗口,每次搜索请求只要在这个时间窗口内完成就可以了。

GET /_index/_type/_search?scroll=1m
{
	"query": {
		"match_all": {}
	},
	"sort": ["_doc"],
	"size": 3
}

和分页不同的是,scroll 类似分页,但使用场景不一样。

分页主要是一页一页的搜索,但 scroll 是一批一批交给系统处理的。