概念
1、概念
一个查询语句究竟具有什么样的行为和得到什么结果,主要取决于它到底是处Query
还是Filter
。两者有很大区别,我们来看下:
Query context 查询上下文
这种语句在执行时既要计算文档是否匹配,还要计算文档相对于其他文档的匹配度有多高,匹配度越高,_score
分数就越高
Filter context 过滤上下文
过滤上下文中的语句在执行时只关心文档是否和查询匹配,不会计算匹配度,也就是得分。
看下官方的例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| GET /_search { "query": { "bool": { "must": [ { "match": { "title": "Search" }}, { "match": { "content": "Elasticsearch" }} ], "filter": [ { "term": { "status": "published" }}, { "range": { "publish_date": { "gte": "2015-01-01" }}} ] } } }
|
对上面的例子分析下:
query
参数表示整个语句是处于 query context 中
bool
和 match
语句被用在 query context 中,也就是说它们会计算每个文档的匹配度(_score)
filter
参数则表示这个子查询处于 filter context 中
filter
语句中的 term
和 range
语句用在 filter context 中,它们只起到过滤的作用,并不会计算文档的得分。
2、查询数据准备
1)创建索引
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| PUT student { "settings":{ "number_of_shards":1, "number_of_replicas":1 }, "mappings":{ "properties":{ "name":{"type":"text"}, "address":{"type":"keyword"}, "age":{"type":"integer"}, "interests":{"type":"text"}, "birthday":{"type":"date"} } } }
|
2)添加测试数据
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 42 43 44 45
| POST /student/_doc/1 { "name":"徐小小", "address":"杭州", "age":3, "interests":"唱歌 画画 跳舞", "birthday":"2017-06-19" }
POST /student/_doc/2 { "name":"刘德华", "address":"香港", "age":28, "interests":"演戏 旅游", "birthday":"1980-06-19" }
POST /student/_doc/3 { "name":"张小斐", "address":"北京", "age":28, "interests":"小品 旅游", "birthday":"1990-06-19" }
POST /student/_doc/4 { "name":"王小宝", "address":"德州", "age":63, "interests":"演戏 小品 打牌", "birthday":"1956-06-19" }
POST /student/_doc/5 { "name":"向华强", "address":"香港", "age":31, "interests":"演戏 主持", "birthday":"1958-06-19" }
|
看是否成功
1
| GET _cat/count/student?v
|
可以看出索引已经存在,并且下面有5条数据。
二、Query查询
1、match查询
match query
: 知道分词器的存在,会对filed进行分词操作,然后再查询
match_all
: 查询所有文档
multi_match
: 可以指定多个字段
match_phrase
: 短语匹配查询,ElasticSearch引擎首先分析(analyze)查询字符串,从分析后的文本中构建短语查询,这意味着必须匹配短语中的所有分词,
并且保证各个分词的相对位置不变
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 42 43 44 45 46
| GET student/_search { "query":{ "match":{"age": 3} } }
GET student/_search { "query":{ "match":{"interests": "演戏"} } }
GET student/_search { "query":{ "match_all": {} } }
GET student/_search { "query":{ "multi_match": { "query": "德", "fields":["name","address"] } } }
GET student/_search { "query":{ "match_phrase":{"interests": "演员"} } }
|
重点
通过上面的例子有两点比较重要
1)、文档字段属性如果是一个keyword
类型,那就需要完全匹配才能命中。好比这个字段值是12345
,那么你不论是1234
还是123456
都不会命中。
2)、如果是match_phrase
,那就是真正的包含关系。好比这个字段值是12345
,那么你是1234
就会命中,而123456
不会命中。因为12345包含1234而不包含123456。
2、term查询和terms查询
term query
: 会去倒排索引中寻找确切的term,它并不知道分词器的存在。这种查询适合keyword 、numeric、date。
term
:查询某个字段为该关键词的文档(它是相等关系而不是包含关系)
terms
:查询某个字段里含有多个关键词的文档
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| GET student/_search { "query":{ "term":{ "address":"香港"} } }
GET student/_search { "query":{ "terms":{ "address":["香港","北京"] } } }
|
3、控制查询返回的数量
1 2 3 4 5 6 7 8 9
| #返回前两条数据 (命中: ID = 2,5) GET student/_search { "from":0, "size":2, "query":{ "match":{"interests": "演戏"} } }
|
4、指定返回的字段
1 2 3 4 5 6 7
| GET student/_search { "_source":["name","age"], "query":{ "match":{"interests": "演戏"} } }
|
5、显示要的字段、去除不需要的字段、可以使用通配符*
1 2 3 4 5 6 7 8 9 10
| GET student/_search { "query":{ "match_all": {} }, "_source":{ "includes": "addr*", "excludes": ["name","bir*"] } }
|
6、排序
1 2 3 4 5 6 7 8 9
| GET student/_search { "query":{ "match_all": {} }, "sort":[{ "age":{"order": "desc"} }] }
|
7、 范围查询
range
: 实现范围查询
include_lower
: 是否包含范围的左边界,默认是true
include_upper
: 是否包含范围的右边界,默认是true
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
| GET student/_search { "query": { "range": { "birthday": { "from": "1950-01-11", "to": "1990-01-11", "include_lower": true, "include_upper": false } } } }
GET student/_search { "query": { "range": { "age": { "from": 18, "to": 28, "include_lower": true, "include_upper": true } } } }
|
8、wildcard查询
允许使用通配符 和 ?来进行查询
`代表0个或多个字符
?` 代表任意一个字符
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| GET student/_search { "query": { "wildcard": { "name": "徐*" } } }
GET student/_search { "query": { "wildcard": { "name": "徐小?" } } }
|
9、fuzzy实现模糊查询
模糊查询可以在Match和 Multi-Match查询中使用以便解决拼写的错误,模糊度是基于Levenshteindistance计算与原单词的距离。使用如下:
1 2 3 4 5 6 7 8 9 10 11 12
| (命中: ID = 2,5,4) GET student/_search { "query": { "fuzzy": { "interests": { "value": "演" } } } }
|
有关fuzzy
描述可以参考一篇文章:Elasticsearch的误拼写时的fuzzy模糊搜索技术
10、高亮搜索结果
1 2 3 4 5 6 7 8 9 10 11 12
| { "query":{ "match":{ "interests": "演戏" } }, "highlight": { "fields": { "interests": {} } } }
|
三、Filter查询
filter是不计算相关性的,同时可以cache。因此,filter速度要快于query
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| GET student/_search { "post_filter":{ "term":{"age": 3} } }
GET student/_search { "post_filter":{ "terms":{"age":[3,63]} } }
|
This is copyright.