Query查詢器 與 Filter 過濾器
盡管我們之前已經涉及了查詢DSL,然而實際上存在兩種DSL:查詢DSL(query DSL)和過濾DSL(filter DSL)。
過濾器(filter)通常用於過濾文檔的范圍,比如某個字段是否屬於某個類型,或者是屬於哪個時間區間
* 創建日期是否在2014-2015年間?
* status字段是否為success?
* lat_lon字段是否在某個坐標的10公里范圍內?
查詢器(query)的使用方法像極了filter,但query更傾向於更准確的查找。
* 與full text search的匹配度最高
* 正則匹配
* 包含run單詞,如果包含這些單詞:runs、running、jog、sprint,也被視為包含run單詞
* 包含quick、brown、fox。這些詞越接近,這份文檔的相關性就越高
查詢器會計算出每份文檔對於某次查詢有多相關(relevant),然后分配文檔一個相關性分數:_score。而這個分數會被用來對匹配了的文檔進行相關性排序。相關性概念十分適合全文搜索(full-text search),這個很難能給出完整、“正確”答案的領域。
query filter在性能上對比:filter是不計算相關性的,同時可以cache。因此,filter速度要快於query。
下面是使用query語句查詢的結果,第一次查詢用了300ms,第二次用了280ms.
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
|
#blog: http://xiaorui.cc
{
"size": 1,
"query": {
"bool": {
"must": [
{
"terms": {
"keyword": [
"手機",
"iphone"
]
}
},
{
"range": {
"cdate": {
"gt": "2015-11-09T11:00:00"
}
}
}
]
}
}
}
{
"took": 51,
"timed_out": false,
"_shards": {
"total": 30,
"successful": 30,
"failed": 0
},
"hits": {
"total": 6818,
"max_score": 0,
"hits": []
}
}
|
下面是使用filter查詢出來的結果,第一次查詢時間是280ms,第二次130ms…. 速度確實快了不少,也證明filter走了cache緩存。 但是如果我們對比下命中的數目,query要比filter要多一點,換句話說,更加的精准。
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
|
#blog: xiaorui.cc
{
"size": 0,
"filter": {
"bool": {
"must": [
{
"terms": {
"keyword": [
"手機",
"iphone"
]
}
},
{
"range": {
"cdate": {
"gt": "2015-11-09T11:00:00"
}
}
}
]
}
}
}
{
"took": 145,
"timed_out": false,
"_shards": {
"total": 30,
"successful": 30,
"failed": 0
},
"hits": {
"total": 6804,
"max_score": 0,
"hits": []
}
}<span style="font-size:13.2px;line-height:1.5;"></span>
|
如果你想同時使用query和filter查詢的話,需要使用 {query:{filtered:{}}} 來包含這兩個查詢語法。他們的好處是,借助於filter的速度可以快速過濾出文檔,然后再由query根據條件來匹配。
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
|
"query": {
"filtered": {
"query": { "match": { "email": "business opportunity" }},
"filter": { "term": { "folder": "inbox" }}
}
}
}
{ "size":0,
"query": {
"filtered": {
"query": {
"bool": {
"should": [],
"must_not": [
],
"must": [
{
"term": {
"channel_name":"微信自媒體微信"
}
}
]
}
}
},
"filter":{
"range": {
"idate": {
"gte": "2015-09-01T00:00:00",
"lte": "2015-09-10T00:00:00"
}
}
}
}
}
|
我們這業務上關於elasticsearch的查詢語法基本都是用query filtered方式進行的,我也推薦大家直接用這樣的方法。should ,must_not, must 都是列表,列表里面可以寫多個條件。 這里再啰嗦一句,如果你的查詢是范圍和類型比較粗大的,用filter ! 如果是那種精准的,就用query來查詢。
{
”bool”:{
”should”:[], #相當於OR條件
”must_not”:[], #必須匹配的條件,這里的條件都會被反義
”must”:[] #必須要有的
}
}
END..