一、查询语法
1、Searchtimeout:
(1) 设置:默认没有timeout,如果设置了timeout,那么会执行timeout机制。
(2) Timeout机制:假设用户查询结果有1W条数据,但是需要10″才能查询完毕,但是用户设置了1″的timeout,那么不管当前一共查询到了多少数据,都会在1″后ES讲停止查询,并返回当前数据。
(3) 用法:GET /_search?timeout=1s/ms/m
2、ES常用查询:
(1) Query_string:
① 查询所有:GET /product/_search
② 带参数:GET /product/_search?q=name:xiaomi
③ 分页:GET /product/_search?from=0&size=2&sort=price:asc
(2) Query DSL:
①match_all
:匹配所有
1 2 3 4 5 6
| GET /product/_search { "query": { "match_all": {} } }
|
②match
:name中包含 “nfc”
1 2 3 4 5 6 7 8
| GET /product/_search { "query": { "match": { "name": "nfc" } } }
|
③sort
:按照价格倒序排序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| GET /product/_search { "query": { "multi_match": { "query": "nfc", "fields": [ "name", "desc" ] } }, "sort": [ { "price": "desc" } ] }
|
④ multi_match
:根据多个字段查询一个关键词,name和desc中包含“nfc”的doc
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| GET /product/_search { "query": { "multi_match": { "query": "nfc", "fields": [ "name", "desc" ] } }, "sort": [ { "price": "desc" } ] }
|
⑤ _source 元数据
:想要查询多个字段,例子中为只查询“name”和“price”字段。
1 2 3 4 5 6 7 8 9 10 11 12
| GET /product/_search { "query": { "match": { "name": "nfc" } }, "_source": [ "name", "price" ] }
|
⑥ 分页(deep-paging)
:查询第一页(每页两条数据)
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| GET /product/_search { "query": { "match_all": {} }, "sort": [ { "price": "asc" } ], "from": 0, "size": 2 }
|
(3) Full-text queries:全文检索
① query-term
:不会被分词,
1 2 3 4 5 6 7 8
| GET /product/_search { "query": { "term": { "name": "nfc" } } }
|
② match
和term
区别:
1 2 3 4 5 6 7 8
| GET /product/_search { "query": { "term": { "name": "nfc phone" } } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| GET /product/_search { "query": { "bool": { "must": [ { "term": { "name": "nfc" } }, { "term": { "name": "phone" } } ] } } }
|
1 2 3 4 5 6 7 8 9 10 11
| GET /product/_search { "query": { "terms": { "name": [ "nfc", "phone" ] } } }
|
1 2 3 4 5 6 7 8
| GET /product/_search { "query": { "match": { "name": "nfc phone" } } }
|
③ ☆全文检索:
1 2 3 4 5 6 7 8
| GET /product/_search { "query": { "match": { "name": "xiaomi nfc zhineng phone" } } }
|
验证分词(text的内容会被分成哪些分词)
1 2 3 4 5
| GET /_analyze { "analyzer": "standard", "text": "xiaomi nfc zhineng phone" }
|
(4)Phrase search:短语搜索
和全文检索相反,“nfc phone”会作为一个短语去检索
1 2 3 4 5 6 7 8
| GET /product/_search { "query": { "match_phrase": { "name": "nfc phone" } } }
|
(5) Query and filter:查询和过滤
① bool
:可以组合多个查询条件
bool查询也是采用more_matches_is_better的机制,因此满足must和should子句的文档将会合并起来计算分值。
must
:必须满足
子句(查询)必须出现在匹配的文档中,并将有助于得分。
filter
:过滤器 不计算相关度分数,cache☆
子句(查询)必须出现在匹配的文档中。但是不像 must
查询的分数将被忽略。Filter子句在filter上下文中执行,这意味着计分被忽略,并且子句被考虑用于缓存。
should
:可能满足 or
子句(查询)应出现在匹配的文档中。
must_not
:必须不满足 不计算相关度分数 not
子句(查询)不得出现在匹配的文档中。子句在过滤器上下文中执行,这意味着计分被忽略,并且子句被视为用于缓存。由于忽略计分,0
因此将返回所有文档的分数。
minimum_should_match
② 案例:
- demo案例
#首先筛选name包含“xiaomi phone”并且价格大于1999的数据(不排序),
#然后搜索name包含“xiaomi”and desc 包含“shouji”
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| GET /product/_search { "query": { "bool": { "must": [ { "match": { "name": "xiaomi" } }, { "match": { "desc": "shouji" } } ], "filter": [ { "match_phrase": { "name": "xiaomi phone" } }, { "range": { "price": { "gt": 1999 } } } ] } } }
|
- bool多条件
name包含xiaomi 不包含erji 描述里包不包含nfc都可以,价钱要大于等于4999
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| GET /product/_search { "query": { "bool": { #name中必须包含“xiaomi” "must": [ { "match": { "name": "xiaomi" } } ], #name中必须不能包含“erji” "must_not": [ { "match": { "name": "erji" } } ], #should中至少满足0个条件,参见下面的**minimum_should_match****的解释** "should": [ { "match": { "desc": "nfc" } } ], #筛选价格大于4999的doc "filter": [ { "range": { "price": { "gt": 4999 } } } ] } } }
|
③ 嵌套查询:
minimum_should_match
:参数指定should返回的文档必须匹配的子句的数量或百分比。如果bool查询包含至少一个should子句,而没有must或 filter子句,则默认值为1。否则,默认值为0**
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| GET /product/_search { "query": { "bool": { "must": [ { "match": { "name": "nfc" } } ], "should": [ { "range": { "price": { "gt": 1999 } } }, { "range": { "price": { "gt": 3999 } } } ], "minimum_should_match": 1 } } }
|
- 案例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| GET /product/_search { "query": { "bool": { "filter": { "bool": { "should": [ { "range": { "price": { "gt": 1999 } } }, { "range": { "price": { "gt": 3999 } } } ], "must": [ { "match": { "name": "nfc" } } ] } } } } }
|
① 想要一台带NFC功能的 或者 小米的手机 但是不要耳机
1 2 3
| SELECT * from product where (`name` like "%xiaomi%" or `name` like '%nfc%') AND `name` not LIKE '%erji%'
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| GET /product/_search { "query": { "constant_score": { "filter": { "bool": { "should": [ { "term": { "name": "xiaomi" } }, { "term": { "name": "nfc" } } ], "must_not": [ { "term": { "name": "erji" } } ] } }, "boost": 1.2 } } }
|
② 搜索一台xiaomi nfc phone或者一台满足 是一台手机 并且 价格小于等于2999
1 2 3 4 5 6
| SELECT * FROM product WHERE NAME LIKE '%xiaomi nfc phone%' OR ( NAME LIKE '%erji%' AND price > 399 AND price <=999);
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| GET /product/_search { "query": { "constant_score": { "filter": { "bool": { "should": [ { "match_phrase": { "name": "xiaomi nfc phone" } }, { "bool": { "must": [ { "term": { "name": "phone" } }, { "range": { "price": { "lte": "2999" } } } ] } } ] } } } } }
|
(7) Highlight search:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| GET /product/_search { "query": { "match_phrase": { "name": "nfc phone" } }, "highlight": { "fields": { "name": {} } } }
|
3、Deep paging深度分页
比如这是一个有5个分片的索引,每个分片有一万条数据,现在用户想查询5001到5050条数据(某个字段由大到小的排序规则下)
假如需要的这50条数据分别在5个分片上(实际情况不能保证所需要的数据在一个分片上),那么在查询的时候,只能讲每个分片的前5050条数据都查出来,然后对这5050*5条数据拿出来,重新排序,然后取5001~5050的数据。
(1) 解释:当你的数据超过1W,不要使用
(2) 返回结果不要超过1000个,500以下为宜
分页的话,每页的数量不要超过500
(3) 解决办法
① 尽量避免深度分页查询
② 使用Scroll search
(只能下一页,没办法上一页,不适合实时查询)
1
| GET /product/_search?scroll=1m
|
这里的1m
是指,在这一分钟内,你可以拿着scroll_id
查询下一个pape的数据,过了1min之后,就查不到了
查询结果中会返回一个scroll_id
,下次查询的时候可以用这个id去查
1 2 3 4 5
| GET /_search/scroll { "scroll":"1m", "scroll_id":"" }
|
因此,Scroll search
解决 deep paging
问题
5、filter缓存原理
如果您喜欢此博客或发现它对您有用,则欢迎对此发表评论。 也欢迎您共享此博客,以便更多人可以参与。 如果博客中使用的图像侵犯了您的版权,请与作者联系以将其删除。 谢谢 !