elasticsearch版本7.3.0
主要记录语句格式,不会囊括所有查询方式
Validate api:
GET /index/_validate/query?explain
用于特别复杂庞大的搜索,如写了上百行的搜索语句,这个时候可以先用validate api去验证一下,搜索是否合法
查询返回结果:
took:耗费了几毫秒
timed_out:是否超时,默认无timeout
_shards:数据拆成了n个分片,所以对于搜索请求,会打到所有的primary shard(或者是它的某个replica shard也可以)
hits.total:查询结果的数量,共有n个document
hits.max_score:本次搜索的所有结果中,最大的相关度分数
hits.hits:包含了匹配搜索的document的详细数据,默认查询前10条数据,完整数据的_score降序排序
元数据:
_index:代表一个文档放在哪个索引中,索引名称必须是小写的,不能用下划线开头,不能包含逗号
_type:代表文档属于index中的哪个类别
_id:文档的唯一标识,与索引和类型一起,定位到一个文档,新增数据时可以指定,也可以默认es创建,数据导入es时可以指定
_version:创建一个document的时候,它的_version内部版本号就是1;之后,每次对这个document执行修改或者删除操作,都会对这个_version版本号自动加1;即使删除,也会对这条数据的版本号加1
_source: 里面指定要返回的字段,默认返回所有
查询结果的排序:
搜索依靠倒排索引,排序依靠正排索引,即doc value。
doc values是被保存在磁盘上的,此时如果内存足够,os会自动将其缓存在内存中;如果内存不足够,操作系统会将其写入磁盘上。
定制排序规则,只需要在查询语句加入sort即可,数组,优先级从上到下:
"sort": [
{
"fieldname": {
"order": "asc"
}
}
]
Multi-index搜索:
/_search:所有索引下的所有数据都搜索出来
/index1/_search:指定一个index,搜索其下所有数据
/index1,index2/_search:同时搜索两个index下的数据
/*1,*2/_search:按照通配符去匹配多个索引
_all,可以代表搜索所有index
query string search:
GET /index/_search?q=field:fieldvalue&sort=field:desc
GET /index/_search?q=+fieldname:fieldvalue +:必须包含;-:必须不包含
query DSL:
GET /index/_search
{
"query": {
"match": {
"fieldname": "fieldvalue"
}
},
"_source": [
"fieldname1",
"fieldname2"
],
"sort": [
{
"fieldname": "desc"
}
]
}
query filter:
每个query查询中的子查询都会计算一个document针对它的相关度分数,然后bool综合所有分数,合并为一个分数,但是filter不计算分数
- filter:按照搜索条件过滤出需要的数据,不计算任何相关度分数,对相关度没有任何影响,性能好,同时内部会自动缓存常使用filter的数据。
- query:会去计算每个document相对于搜索条件的相关度,并按照相关度进行排序,性能差,无缓存,但可以按照分数排序。
GET /index/_search
{
"query": {
"bool": {
"must": {
"match": {
"fieldname": "fieldvalue"
}
},
"filter": {
"range": {
"field": {
"gt": 0,
"lt": 1
}
}
}
}
},
"size": 1
}
phrase search(短语搜索):
完全匹配条件
GET /index/_search
{
"query": {
"match_phrase": {
"fieldname": "fieldvalue"
}
}
}
highlight search(高亮搜索结果):
GET /index/_search
{
"query": {
"match": {
"fieldname": "fieldvalue"
}
},
"highlight": {
"fields": {
"fieldname": {}
}
}
}
multi match:
多字段匹配
GET /index/_search
{
"query": {
"multi_match": {
"query": "fieldvalue",
"fields": [
"fieldname1",
"fieldname2"
]
}
}
}
聚合搜索:
GET /index/_search
{
"size": 0,
"aggs": {
"agg_name": {
"terms": {
"field": "fieldname"
}
}
}
}
聚合搜索之后求平均值,并且按照平均数降序排序
GET /index/_search
{
"size": 0,
"aggs": {
"agg_name1": {
"terms": {
"field": "fieldname",
"order": {
"agg_name2": "desc"
}
},
"aggs": {
"agg_name2": {
"avg": {
"field": "fieldname"
}
}
}
}
}
}
按照指定区间分组,并计算平均数:
GET /index/_search
{
"size": 0,
"aggs": {
"agg_name1": {
"range": {
"field": "fieldname(age)",
"ranges": [
{
"from": 0,
"to": 20
},
{
"from": 20,
"to": 40
},
{
"from": 40,
"to": 50
}
]
},
"aggs": {
"agg_name2": {
"terms": {
"field": "fieldname"
},
"aggs": {
"agg_name3": {
"avg": {
"field": "fieldname"
}
}
}
}
}
}
}
}
聚合去重:
GET /index/_search
{
"size": 0,
"query": {
"bool": {
"must": [
{
"match": {
"fieldname": "fieldvalue"
}
},
{
"range": {
"fieldname": {
"gte": fieldvalue1,
"lte": fieldvalue2,
"format": "epoch_millis"
}
}
}
]
}
},
"aggs": {
"agg_name": {
"cardinality": {
"field": "fieldname"
}
}
}
}
批量查询:
批量查询可以减少网络连接次数,性能优化会非常明显
GET /_mget
{
"docs": [
{
"_index": "indexname1",
"_id": "id1"
},
{
"_index": "indexname2",
"_id": "id2"
}
]
}
同一索引下:
GET /index/_mget
{
"ids": ["id1", "id2"]
}
timeout机制:
指定timeout,如:添加参数?timeout=1m
timeout机制原理指限定在一定时间内,将部分获取到的数据直接返回,避免查询耗时过长
分页查询:
from,size分页查询:
GET /index/_search
{
"from": 0,
"size": 5
}
数据量大的情况不建议,会让所有节点全返回前5条,然后协调节点合并再去5条。
scroll api
- 滚动搜索,先搜索一批数据,然后下次再搜索一批数据,以此类推,直到搜索出全部的数据来。
- 会在第一次搜索的时候,保存一个视图快照,之后只会基于该视图快照提供数据搜索,期间用户不会看到正在修改的数据
- 采用基于_doc进行排序的方式,性能较高
- 每次发送scroll请求,我们还需要指定一个scroll参数,指定一个时间窗口,每次搜索请求只要在这个时间窗口内能完成就可以了
- 第一次之后的每次搜索都要带上返回的scroll id
第一次查询:
GET /index/_search?scroll=1m
{
"query": {
"match_all": {}
},
"sort": [
"_doc"
],
"size": 1
}
第二次查询:
GET /_search/scroll
{
"scroll": "1m",
"scroll_id": "J5VGh...lbkZldG"
}
get请求和post请求都支持
-----------------------------------------------------
bouncing results问题:
两个document排序,field值相同;不同的shard上,可能排序不同;每次请求轮询打到不同的replica shard上;
每次页面上看到的搜索结果的排序都不一样。这就是bouncing result,也就是跳跃的结果。
解决方案:将preference设置为一个字符串如用户id之类,也可以设置routing值