注:此文檔僅適用于 Elasticsearch > 5.0 版本
Elasticsearch 的功能之一就是搜索闻牡,搜索主要分為兩種類型,結(jié)構(gòu)化搜索和全文搜索绳矩。結(jié)構(gòu)化搜索是指有關(guān)探詢那些具有內(nèi)在結(jié)構(gòu)數(shù)據(jù)的過(guò)程罩润。比如日期、時(shí)間和數(shù)字都是結(jié)構(gòu)化的:它們有精確的格式翼馆,我們可以對(duì)這些格式進(jìn)行邏輯操作割以。比較常見(jiàn)的操作包括比較數(shù)字或時(shí)間的范圍,或判定兩個(gè)值的大小写妥。
結(jié)構(gòu)化搜索的特征是『非是即否』拳球,一個(gè)文檔要么存于集合之中,要么存在集合之外珍特。
EndPoints
經(jīng)常的情況下祝峻,需要在一個(gè)或多個(gè)特殊的索引并且在一個(gè)或者多個(gè)特殊的類型中進(jìn)行搜索。我們可以通過(guò)在URL中指定特殊的索引和類型達(dá)到這種效果扎筒,如下所示:
/_search
:在所有的索引中搜索所有的類型
/gb/_search
:在 gb
索引中搜索所有的類型
/gb,us/_search
:在 gb
和 us
索引中搜索所有的文檔
/g*,u*/_search
:在任何以 g
或者 u
開(kāi)頭的索引中搜索所有的類型
/gb/user/_search
:在 gb
索引中搜索 user
類型
/gb,us/user,tweet/_search
:在 gb
和 us
索引中搜索 user
和 tweet
類型
/_all/user,tweet/_search
:在所有的索引中搜索 user
和 tweet
類型
精確值查詢
在 Elasticsearch 中莱找,過(guò)濾器不能夠單獨(dú)使用,它必須和 query
一起使用嗜桌,例如下面的查詢例子奥溺。其中 constant_score
表示查詢以非評(píng)分模式進(jìn)行,這樣可以省掉評(píng)分過(guò)程骨宠,提高查詢速度浮定。
GET /my_store/products/_search
{
"query" : {
"constant_score" : {
"filter" : {
"term" : {
"price" : 20
}
}
}
}
}
如果需要查找 object
里面的字段相满,可以使用點(diǎn)語(yǔ)法,例如:
{
"query" : {
"constant_score" : {
"filter" : { "term" : { "user.id" : 1 } }
}
}
}
常用的過(guò)濾器包含 term
桦卒、 terms
立美、 range
、 prefix
方灾、 wildcard
建蹄、 regexp
、 exists
裕偿、 missing
洞慎。下面進(jìn)行一一介紹。
term
term 代表完全匹配嘿棘,也就是精確查詢劲腿。
注:查詢字符串時(shí),查詢的字段類型必須是
keyword
蔫巩,如果查詢的是text
谆棱, 則有可能查詢結(jié)果不正確。
{
"query" : {
"constant_score" : {
"filter" : {"term" : { "price" : 20 } }
}
}
}
terms
terms
查詢類似于 SQL
中的 in
關(guān)鍵詞圆仔。例如:
{
"query": {
"constant_score" : {
"filter" : {"terms" : { "user" : ["kimchy", "elasticsearch"]}}
}
}
}
range
range
主要用于數(shù)字和日期類型的字段查詢垃瞧。例如查詢年齡在 10
到 20
歲的用戶:
{
"query": {
"constant_score" : {
"filter" : {"range" : { "age" : { "gte" : 10, "lte" : 20 } } }
}
}
}
range
接受以下幾個(gè)參數(shù):
- gte:大于等于
- gt:大于
- lte:小于等于
- le:小于
當(dāng)查詢字段的類型是日期時(shí),可以添加 format
類型的字段坪郭,如果時(shí)間字段與時(shí)區(qū)相關(guān)个从,則還可以添加 time_zone
字段。
{
"query": {
"constant_score" : {
"filter" : {
"range" : {
"age" : {
"gte" : "2015-01-01 00:00:00",
"lte" : "2015-02-01 00:00:00",
"format": "yyyy-MM-dd HH:mm:ss",
"time_zone": "+01:00"
}
}
}
}
}
}
prefix
prefix
又稱前綴查詢歪沃,用于 keyword
類型的字段查詢嗦锐。
{
"query" : {
"constant_score" : {
"filter" : {
"prefix" : { "name" : "ki" }
}
}
}
}
wildcard
wildcard
又稱通配符查詢,也是用于 keyword
類型的字段查詢沪曙。通配符查詢主要基于 shell 的通配符: ?
匹配任意字符奕污, *
匹配 0 或多個(gè)字符。
{
"query" : {
"constant_score" : {
"filter" : {
"wildcard" : { "name" : "ki*y" }
}
}
}
}
regexp
regexp
又稱正則查詢液走,也是用于 keyword
類型的字段查詢碳默。
{
"query" : {
"constant_score" : {
"filter" : {
"regexp" : { "name" : "s.*y" }
}
}
}
}
exists 和 missing
exists
字段類似于 SQL
中的 IS NOT NULL
,用于過(guò)濾指定字段不為 NULL 的文檔缘眶。
{
"query" : {
"constant_score" : {
"filter" : {
"exists" : { "field" : "tags" }
}
}
}
}
missing
與 exists
正相反嘱根,它返回指定字段為 NULL 的文檔。
bool 過(guò)濾器
bool 過(guò)濾器是一個(gè)復(fù)合過(guò)濾器(Compound filter)巷懈,它可以接受多個(gè)其他過(guò)濾器作為參數(shù)该抒,并將這些過(guò)濾器結(jié)合成各式各樣的布爾(邏輯)組合。
一個(gè) bool
過(guò)濾器由三部分組成:
{
"bool" : {
"must" : [],
"should" : [],
"must_not" : [],
"filter": []
}
}
-
must
: 所有的語(yǔ)句都 必須(must) 匹配顶燕,與AND
等價(jià)凑保。 -
must_not
:所有的語(yǔ)句都 不能(must not) 匹配冈爹,與NOT
等價(jià)。 -
should
:至少有一個(gè)語(yǔ)句要匹配愉适,與OR
等價(jià)犯助。 -
filter
:表示這是一個(gè)過(guò)濾器,與 must 等價(jià)维咸。
filter 的結(jié)果會(huì)緩存,因此盡量使用 filter 關(guān)鍵詞惠爽。
{
"query" : {
"filtered" : {
"filter" : {
"bool" : {
"should" : [
{ "term" : {"price" : 20}},
{ "term" : {"productID" : "XHDK-A-1293-#fJ3"}}
],
"must_not" : {
"term" : {"price" : 30}
}
}
}
}
}
}
上面的查詢等同于 (price = 20 OR productID='XHDK-A-1293-#fJ3') AND price != 30
癌蓖。
nested 查詢
nested
類型的字段,由于索引在獨(dú)立的文檔中婚肆,我們無(wú)法通過(guò)點(diǎn)語(yǔ)法直接搜索他們租副。因此 Elasticsearch 開(kāi)發(fā)了 nested
查詢,這個(gè)查詢主要用于查詢 nested
類型字段中的對(duì)象的字段较性。
{
"query": {
"nested": {
"path": "comments",
"query": {
"bool": {
"filter": {
{"term": {"comments.name": "john"}}
}
}
}
}
}
}
排序和分頁(yè)
默認(rèn)情況下用僧,查詢返回的結(jié)果會(huì)按照 _score
進(jìn)行排序,值越高越靠前赞咙。咱結(jié)構(gòu)化搜索中责循,_score
的只都是相等的,因此結(jié)果會(huì)按照隨機(jī)順序返回攀操。
Elasticsearch 提供了結(jié)果排序的功能院仿,可以使用 sort
字段指定排序的方式。
{
"query" : {
"bool" : {
"filter" : { "term" : { "user_id" : 1 }}
}
},
"sort": { "date": { "order": "desc" }}
}
也可以指定多個(gè)字段進(jìn)行排序:
{
"query" : {
"bool" : {
"filter" : { "term" : { "user_id" : 1 }}
}
},
"sort": [
{ "date": { "order": "desc" }},
{ "name": { "order": "esc" }}
]
}
有了排序功能速和,就需要分頁(yè)歹垫。分頁(yè)有 size
和 from
兩個(gè)參數(shù)指定。
-
size
:返回的結(jié)果數(shù)量颠放,默認(rèn)10 -
from
:跳過(guò)開(kāi)始的結(jié)果數(shù)排惨,默認(rèn)0
下面的例子表示請(qǐng)求第三頁(yè)的數(shù)據(jù)。
{
"query" : {
"bool" : {
"filter" : { "term" : { "user_id" : 1 }}
}
},
"sort": { "date": { "order": "desc" }},
"size": 10,
"from": 20
}
在 Elasticsearch 中碰凶,返回的結(jié)果隨著分頁(yè)的增長(zhǎng)而成倍增長(zhǎng)暮芭。
現(xiàn)在假設(shè)我們請(qǐng)求第1000頁(yè)——結(jié)果10001到10010。工作方式都相同痒留,不同的是每個(gè)分片都必須產(chǎn)生頂端的10010個(gè)結(jié)果谴麦。然后請(qǐng)求節(jié)點(diǎn)排序這50050個(gè)結(jié)果并丟棄50040個(gè)!
因此盡量避免使用深度分頁(yè)伸头。如果有大量分頁(yè)的需求匾效,可以使用 Scrolling 的方式。
參考資料: