document数据格式
面向文档的搜索分析引擎
Elasticsearch 使用 JavaScript Object Notation(或者 JSON)作为文档的序列化格式。JSON 序列化为大多数编程语言所支持,并且已经成为 NoSQL 领域的标准格式。 它简单、简洁、易于阅读。
简单的集群管理
es提供了一套api,叫做cat api,可以查看es中各种各样的数据
GET /_cat/health?v
epoch timestamp cluster status node.total node.data shards pri relo init unassign pending_tasks max_task_wait_time active_shards_percent
1606447321 03:22:01 elasticsearch yellow 1 1 7 7 0 0 1 0 - 87.5%
green:每个索引的primary shard和replica shard都是active状态的
yellow:每个索引的primary shard都是active状态的,但是部分replica shard不是active状态,处于不可用的状态
red:不是所有索引的primary shard都是active状态的,部分索引有数据丢失了
为什么现在会处于一个yellow状态?
我们现在就一个笔记本电脑,就启动了一个es进程,相当于就只有一个node。现在es中有一个index,就是kibana自己内置建立的index。由于默认的配置是给每个index分配5个primary shard和5个replica shard,而且primary shard和replica shard不能在同一台机器上(为了容错)。现在kibana自己建立的index是1个primary shard和1个replica shard。当前就一个node,所以只有1个primary shard被分配了和启动了,但是一个replica shard没有第二台机器去启动。
此时只要启动第二个es进程,就会在es集群中有2个node,然后那1个replica shard就会自动分配过去,然后cluster status就会变成green状态。
cat命令
/_cat/allocation #查看单节点的shard分配整体情况
/_cat/shards #查看各shard的详细情况
/_cat/shards/{index} #查看指定分片的详细情况
/_cat/master #查看master节点信息
/_cat/nodes #查看所有节点信息
/_cat/indices #查看集群中所有index的详细信息
/_cat/indices/{index} #查看集群中指定index的详细信息
/_cat/segments #查看各index的segment详细信息,包括segment名, 所属shard, 内存(磁盘)占用大小, 是否刷盘
/_cat/segments/{index}#查看指定index的segment详细信息
/_cat/count #查看当前集群的doc数量
/_cat/count/{index} #查看指定索引的doc数量
/_cat/recovery #查看集群内每个shard的recovery过程.调整replica。
/_cat/recovery/{index}#查看指定索引shard的recovery过程
/_cat/health #查看集群当前状态:红、黄、绿
/_cat/pending_tasks #查看当前集群的pending task
/_cat/aliases #查看集群中所有alias信息,路由配置等
/_cat/aliases/{alias} #查看指定索引的alias信息
/_cat/thread_pool #查看集群各节点内部不同类型的threadpool的统计信息,
/_cat/plugins #查看集群各个节点上的plugin信息
/_cat/fielddata #查看当前集群各个节点的fielddata内存使用情况
/_cat/fielddata/{fields} #查看指定field的内存使用情况,里面传field属性对应的值
/_cat/nodeattrs #查看单节点的自定义属性
/_cat/repositories #输出集群中注册快照存储库
/_cat/templates #输出当前正在存在的模板信息
简单CRUD操作
创建索引:PUT /test_index?pretty
查询索引:GET _cat/indices?v
删除索引:DELETE /test_index?pretty
v是带标题 pretty是美化输出
es会自动建立index和type,不需要提前创建,而且es默认会对document每个field都建立倒排索引,让其可以被搜索
添加数据:
PUT /phone/_doc/1
{
"brand":"xiaomi",
"price":1999,
"title":"小米10 至尊纪念版",
"tag":["双模5G","骁龙865","120HZ高刷新率","120倍长焦镜头","120W快充","NFC"]
}
PUT /phone/_doc/2
{
"brand":"vivo",
"price":1099,
"title":"vivo Y30",
"tag":["智慧美颜","5G"]
}
PUT /phone/_doc/3
{
"brand":"huawei",
"price":2999,
"title":"华为 HUAWEI P40 Pro",
"tag":["麒麟990","5000万超感知徕卡四摄","50倍数字变焦"]
}
PUT /phone/_doc/4
{
"brand":"apple",
"price":3999,
"title":"Apple iPhone 11",
"tag":["4G","双卡双待"]
}
检索数据:
GET /phone/_doc/1
替换文档:
PUT /phone/_doc/2
{
"brand":"vivo",
"price":1099,
"title":"vivo Y30",
"tag":["智慧美颜","5G"]
}
替换方式有一个不好,即使必须带上所有的field,才能去进行信息的修改
修改文档:
POST /phone/_doc/2/_update
{
"price":"1199",
}
删除文档:
DELETE /phone/_doc/2
Elasticsearch搜索语法
timeout:
(1)设置:默认没有timeout,如果设置了timeout,那么会执行timeout机制。
(2)Timeout机制:假设用户查询结果有1W条数据,但是需要10″才能查询完毕,但是用户设置了1″的timeout,那么不管当前一共查询到了多少数据,都会在1″后ES讲停止查询,并返回当前数据。
(3)用法:GET /_search?timeout=1s/ms/m
1.query string search
query string search的由来,因为search参数都是以http请求的query string来附带的.
用于临时的在命令行使用一些工具,比如curl,快速的发出请求,来检索想要的信息;但是如果查询请求很复杂,是很难去构建的
在生产环境中,几乎很少使用query string search
查询所有:GET /phone/_search
带参数:GET /phone/_search?q=brand:xiaomi
分页:GET /phone/_search?from=0&size=2&sort=price:asc
2.DSL- 领域特定语言
Domain Specified Language,特定领域的语言
http request body:请求体,可以用json的格式来构建查询语法,比较方便,可以构建各种复杂的语法
//查询全部
GET /phone/_search
{
"query": {
"match_all": {}
}
}
//按字段查询
GET /phone/_search
{
"query": {
"match": {
"brand": "huawei"
}
}
}
// 按价格排序
GET /phone/_search
{
"query": {
"match_all": {}
},
"sort": [
{
"price": {
"order": "desc"
}
}
]
}
//多个字段查询一个关键词
GET /phone/_search
{
"query": {
"multi_match": {
"query": "apple",
"fields": ["brand","title"]
}
}
}
//_source 查询指定字段
GET /phone/_search
{
"query": {
"match_all": {}
},
"_source": ["title","price"]
}
//分页
GET /phone/_search
{
"query": {
"match_all": {}
},
"from": 2,
"size": 4
}
//filter 过滤器
GET /phone/_search
{
"query": {
"bool": {
"must": [
{"match": {
"brand": "apple"
}}
],
"filter": [
{"range": {
"price": {
"gte": 3000,
"lte": 4000
}
}}
]
}
}
}
3.full-text search(全文检索)
GET /phone/_search
{
"query": {
"match": {
"title": "11"
}
}
}
GET /phone/_search
{
"query": {
"match": {
"tag": "5G"
}
}
}
4.phrase search(短语搜索)
跟全文检索相对应,相反,全文检索会将输入的搜索串拆解开来,去倒排索引里面去一一匹配,只要能匹配上任意一个拆解后的单词,就可以作为结果返回
phrase search,要求输入的搜索串,必须在指定的字段文本中,完全包含一模一样的,才可以算匹配,才能作为结果返回
GET /phone/_search
{
"query": {
"match": {
"title": "apple 11"
}
}
}
5.highlight search(高亮搜索结果)
GET /phone/_search
{
"query": {
"match": {
"title": "apple"
}
},
"highlight": {
"fields": {"title": {}}
}
}
返回结果:
{
"took" : 135,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 1.3940738,
"hits" : [
{
"_index" : "phone",
"_type" : "_doc",
"_id" : "4",
"_score" : 1.3940738,
"_source" : {
"brand" : "apple",
"price" : 3999,
"title" : "Apple iPhone 11",
"tag" : [
"4G",
"双卡双待"
]
},
"highlight" : {
"title" : [
"<em>Apple</em> iPhone 11"
]
}
}
]
}
}
特殊
match和term查询的区别
match
- match的查询词会被分词
- match_phrase 不会分词
- match_phrase 可对多个字段进行匹配 term
- term代表完全匹配,不进行分词器分析
- term 查询的字段需要在mapping的时候定义好,否则可能词被分词。传入指定的字符串,查不到数据
bool联合查询
Query and filter:查询和过滤
- bool:可以组合多个查询条件,bool查询也是采用more_matches_is_better的机制,因此满足must和should子句的文档将会合并起来计算分值。
1)must:必须满足
子句(查询)必须出现在匹配的文档中,并将有助于得分。
2)filter:过滤器 不计算相关度分数,cache☆
子句(查询)必须出现在匹配的文档中。但是不像 must查询的分数将被忽略。Filter子句在filter上下文中执行,这意味着计分被忽略,并且子句被考虑用于缓存。
3)should:可能满足 or
子句(查询)应出现在匹配的文档中。
4)must_not:必须不满足 不计算相关度分数 not
子句(查询)不得出现在匹配的文档中。子句在过滤器上下文中执行,这意味着计分被忽略,并且子句被视为用于缓存。由于忽略计分,0因此将返回所有文档的分数。
5)minimum_should_match
参数指定should返回的文档必须匹配的子句的数量或百分比。如果bool查询包含至少一个should子句,而没有must或 filter子句,则默认值为1。否则,默认值为0
Deep paging
搜索过深的时候就需要在node上保存大量的数据,还要进行大量数据的排序,排序之后再取出对应的那一页,所以这个过程,既消耗网络宽带,耗费内存,还消耗cpu。这就是deep paging的性能问题,我们应该尽量避免出现这种deep paging操作。
elasticsearch提出了一个scroll滚动的方式,这个滚动的方式原理就是通过每次查询后,返回一个scroll_id。根据这个scroll_id 进行下一页的查询。可以把这个scroll_id理解为通常关系型数据库中的游标。但是,这种scroll方式的缺点是不能够进行反复查询,也就是说,只能进行下一页,不能进行上一页。
# 先查询第一页(这里的1m代表的是持续滚动时间,如果过了1分钟,还没有查询下一页,那么这个scroll_id就会失效)
GET /phone/_search?scroll=1m
{
"query": {
"match_all": {}
},
"size": 2
}
# 在根据scroll_id查询下一页
POST /_search/scroll
{
"scroll": "1m",
"scroll_id":"FGluY2x1ZGVfY29udGV4dF91dWlkDXF1ZXJ5QW5kRmV0Y2gBFnZVX0YyNURsU3Z5eVNQWmY2cWc5VFEAAAAAAAAfwRZYNjJ6X0I0c1J2Q21OVzBJTXFxYWFR"
}
# 删除所有
DELETE /_search/scroll/_all
# 删除
DELETE /_search/scroll/{scroll_id}
- 原理
-- 初始化时将所有符合搜索条件的搜索结果缓存起来,可以想象成快照
-- 在遍历时,从这个快照里取数据
-- 也就是说,在初始化后对索引插入、删除、更新数据都不会影响遍历结果
游标可以增加性能的原因,是因为如果做深分页,每次搜索都必须重新排序,非常浪费,使用scroll就是一次把要用的数据都排完了,分批取出
filter 原理
聚合分析
Elasticsearch 有一个功能叫聚合(aggregations),允许我们基于数据生成一些精细的分析结果。聚合与 SQL 中的 GROUP BY 类似但更强大。
计算每个tag下的商品数量
// 将文本field的fielddata属性设置为true
PUT /phone
{
"mappings": {
"properties": {
"tag":{
"type": "text",
"fielddata": true
}
}
}
}
// 查询聚合语句
GET /phone/_search
{
"aggs": {
"all_tag": {
"terms": {
"field": "tag",
"size": 100000
}
}
}
}
对名称中包含xiaomi的商品,计算每个tag下的商品数量
GET /phone/_search
{
"query": {
"match": {
"brand": "xiaomi"
}
},
"aggs": {
"all_tag": {
"terms": {
"field": "tag",
"size": 100000
}
}
}
}
先分组,再算每组的平均值,计算每个tag下的商品的平均价格
GET /phone/_search
{
"aggs": {
"all_tag": {
"terms": {
"field": "tag",
"size": 100000
},
"aggs": {
"all_avg": {
"avg": {
"field": "price"
}
}
}
}
}
}
计算每个tag下的商品的平均价格,并且按照平均价格降序排序
GET /phone/_search
{
"aggs": {
"all_tag": {
"terms": {
"field": "tag",
"order": {
"all_avg": "desc"
},
"size": 100000
},
"aggs": {
"all_avg": {
"avg": {
"field": "price"
}
}
}
}
}
}
ElasticSearch完整目录
1. Elasticsearch是什么
2.Elasticsearch基础使用
3.Elasticsearch Mapping
4.Elasticsearch 集群原理
5.Elasticsearch Scripts和读写原理
6.Elasticsearch 分词器
7.Elasticsearch TF-IDF算法及高级查询
8.Elasticsearch 地理位置及搜索
9.Elasticsearch ELK