空搜索
搜索API的最基礎(chǔ)的形式是沒有指定任何查詢的空搜索 ,它簡單地返回集群中所有索引下的所有文檔:
GET /_search
返回的結(jié)果(為了界面簡潔編輯過的)像這樣:
{
"hits" : {
"total" : 14,
"hits" : [
{
"_index": "us",
"_type": "tweet",
"_id": "7",
"_score": 1,
"_source": {
"date": "2014-09-17",
"name": "John Smith",
"tweet": "The Query DSL is really powerful and flexible",
"user_id": 2
}
},
... 9 RESULTS REMOVED ...
],
"max_score" : 1
},
"took" : 4,
"_shards" : {
"failed" : 0,
"successful" : 10,
"total" : 10
},
"timed_out" : false
}
-
hits
返回結(jié)果中最重要的部分是 hits ,它 包含 total 字段來表示匹配到的文檔總數(shù),并且一個 hits 數(shù)組包含所查詢結(jié)果的前十個文檔。
-
took
took 值告訴我們執(zhí)行整個搜索請求耗費(fèi)了多少毫秒。
-
shards
_shards 部分 告訴我們在查詢中參與分片的總數(shù),以及這些分片成功了多少個失敗了多少個。
-
timeout
timed_out 值告訴我們查詢是否超時。默認(rèn)情況下,搜索請求不會超時。 如果低響應(yīng)時間比完成結(jié)果更重要,你可以指定 timeout 為 10 或者 10ms(10毫秒),或者 1s(1秒)
GET /_search?timeout=10ms
在請求超時之前,Elasticsearch 將會返回已經(jīng)成功從每個分片獲取的結(jié)果。應(yīng)當(dāng)注意的是 timeout 不是停止執(zhí)行查詢,它僅僅是告知正在協(xié)調(diào)的節(jié)點(diǎn)返回到目前為止收集的結(jié)果并且關(guān)閉連接。在后臺,其他的分片可能仍在執(zhí)行查詢即使是結(jié)果已經(jīng)被發(fā)送了。
多索引,多類型
如果不對某一特殊的索引或者類型做限制,就會搜索集群中的所有文檔。Elasticsearch 轉(zhuǎn)發(fā)搜索請求到每一個主分片或者副本分片,匯集查詢出的前10個結(jié)果,并且返回給我們。
然而,經(jīng)常的情況下,你 想在一個或多個特殊的索引并且在一個或者多個特殊的類型中進(jìn)行搜索。我們可以通過在URL中指定特殊的索引和類型達(dá)到這種效果,如下所示:
-
/_search
在所有的索引中搜索所有的類型
-
/gb/_search
在 gb 索引中搜索所有的類型
-
/gb,us/_search
在 gb 和 us 索引中搜索所有的文檔
-
/g,u/_search
在任何以 g 或者 u 開頭的索引中搜索所有的類型
-
/gb/user/_search
在 gb 索引中搜索 user 類型
-
/gb,us/user,tweet/_search
在 gb 和 us 索引中搜索 user 和 tweet 類型
-
/_all/user,tweet/_search
在所有的索引中搜索 user 和 tweet 類型
分頁
在之前的 空搜索 中說明了集群中有 14 個文檔匹配了(empty)query 。 但是在 hits 數(shù)組中只有 10 個文檔。如何才能看到其他的文檔?
和 SQL 使用 LIMIT 關(guān)鍵字返回單個 page 結(jié)果的方法相同,Elasticsearch 接受 from 和 size 參數(shù):
-
size
顯示應(yīng)該返回的結(jié)果數(shù)量,默認(rèn)是 10
-
from
顯示應(yīng)該跳過的初始結(jié)果數(shù)量,默認(rèn)是 0
如果每頁展示 5 條結(jié)果,可以用下面方式請求得到 1 到 3 頁的結(jié)果:
GET /_search?size=5
GET /_search?size=5&from=5
GET /_search?size=5&from=10
-
在分布式系統(tǒng)中深度分頁
理解為什么深度分頁是有問題的,我們可以假設(shè)在一個有 5 個主分片的索引中搜索。 當(dāng)我們請求結(jié)果的第一頁(結(jié)果從 1 到 10 ),每一個分片產(chǎn)生前 10 的結(jié)果,并且返回給 協(xié)調(diào)節(jié)點(diǎn) ,協(xié)調(diào)節(jié)點(diǎn)對 50 個結(jié)果排序得到全部結(jié)果的前 10 個。
現(xiàn)在假設(shè)我們請求第 1000 頁--結(jié)果從 10001 到 10010 。所有都以相同的方式工作除了每個分片不得不產(chǎn)生前10010個結(jié)果以外。 然后協(xié)調(diào)節(jié)點(diǎn)對全部 50050 個結(jié)果排序最后丟棄掉這些結(jié)果中的 50040 個結(jié)果。
可以看到,在分布式系統(tǒng)中,對結(jié)果排序的成本隨分頁的深度成指數(shù)上升。這就是 web 搜索引擎對任何查詢都不要返回超過 1000 個結(jié)果的原因。
輕量搜索
一種是 “輕量的” 查詢字符串 版本,要求在查詢字符串中傳遞所有的 參數(shù)。
查詢字符串搜索非常適用于通過命令行做即時查詢。例如,查詢在 tweet 類型中 tweet 字段包含 elasticsearch 單詞的所有文檔:
GET /_all/tweet/_search?q=tweet:elasticsearch
下一個查詢在 name 字段中包含 john 并且在 tweet 字段中包含 mary 的文檔。實(shí)際的查詢就是這樣
+name:john +tweet:mary
但是查詢字符串參數(shù)所需要的 URL編碼,實(shí)際上更加難懂:
GET /_search?q=%2Bname%3Ajohn+%2Btweet%3Amary
+ 前綴表示必須與查詢條件匹配。類似地, - 前綴表示一定不與查詢條件匹配。沒有 + 或者 - 的所有其他條件都是可選的——匹配的越多,文檔就越相關(guān)。
- _all字段
這個簡單搜索返回包含 mary 的所有文檔:
GET /_search?q=mary
之前的例子中,我們在 tweet 和 name 字段中搜索內(nèi)容。然而,這個查詢的結(jié)果在三個地方提到了 mary。
Elasticsearch 是如何在三個不同的字段中查找到結(jié)果的呢?
當(dāng)索引一個文檔的時候,Elasticsearch 取出所有字段的值拼接成一個大的字符串,作為 _all 字段進(jìn)行索引。
- 更復(fù)雜的查詢
下面的查詢針對tweents類型,并使用以下的條件:
- name 字段中包含 mary 或者 john
- date 值大于 2014-09-10
- all 字段包含 aggregations 或者 geo
+name:(mary john) +date:>2014-09-10 +(aggregations geo)
查詢字符串在做了適當(dāng)?shù)木幋a后,可讀性很差:
?q=%2Bname%3A(mary+john)+%2Bdate%3A%3E2014-09-10+%2B(aggregations+geo)
不推薦直接向用戶暴露查詢字符串搜索功能,除非對于集群和數(shù)據(jù)來說非常信任他們。在生產(chǎn)環(huán)境中更多地使用功能全面的 request body 查詢API。