結(jié)構(gòu)化搜索
非黑即白。結(jié)構(gòu)化查詢不關(guān)心文件的相關(guān)度,簡(jiǎn)單的對(duì)文檔包括或排除處理
精確值查找
盡可能多的使用過(guò)濾式查詢(容易被緩存)
1、term查詢數(shù)字
可以用來(lái)處理數(shù)字、布爾值、日期以及文本
{
"term" : {
"price" : 20
}
}
通常當(dāng)查詢一個(gè)精確值的時(shí)候,我們不希望對(duì)他進(jìn)行評(píng)分。
可以是用constant_score查詢以非評(píng)分的方式來(lái)執(zhí)行term
GET /my_store/products/_search
{
"query" : {
"constant_score" : {
"filter" : {
"term" : {
"price" : 20
}
}
}
}
}
2、term查詢文本
只有設(shè)置成not_analyzed的文本字段才來(lái)精確查找
內(nèi)部過(guò)濾器的操作
1、查詢匹配文檔
term查詢?cè)诘古潘饕胁檎易侄危](méi)有設(shè)置成not_analyzed的文本會(huì)分析拆成多個(gè)字段,導(dǎo)致在倒排索引中查詢不到)
2、創(chuàng)建bitset(一個(gè)只包含0和1的數(shù)組)
表示哪個(gè)文檔會(huì)包含該term。文檔存儲(chǔ)是有順序的,包含term的文檔會(huì)被bitset標(biāo)記成1
3、迭代bitset(s)
一旦為每個(gè)查詢生成了bitsets,es就會(huì)循環(huán)迭代bitsets找到滿足所有過(guò)濾條件的匹配文檔的集合。
執(zhí)行順序是啟發(fā)式的,但一般來(lái)說(shuō)先迭代稀疏的bitset
4、增量使用計(jì)數(shù)
es能夠緩存非評(píng)分查詢,但它也會(huì)緩存一些極少使用的東西。
非評(píng)分查詢因?yàn)榈古潘饕呀?jīng)非??炝?,所以我們只想緩存那些我們“在將來(lái)會(huì)被再次使用的查詢”
es會(huì)跟蹤保留查詢使用的歷史狀態(tài),查詢?cè)谧罱?56次查詢中會(huì)被用到,就會(huì)被緩存
當(dāng)bitset被緩存后,緩存會(huì)在那些低于10000個(gè)文檔(或少于3%的總索引數(shù))的segment中被忽略。
這些小的segment將會(huì)消失,所以為它們分配緩存是一種浪費(fèi)
實(shí)際情況并非如此(執(zhí)行有它的復(fù)雜性,這取決于查詢計(jì)劃是如何重新規(guī)劃的,有些啟發(fā)式的算法是基于查詢代價(jià)的),理論上非評(píng)分查詢 先于 評(píng)分查詢執(zhí)行。非評(píng)分查詢?nèi)蝿?wù)旨在降低那些將對(duì)評(píng)分查詢計(jì)算帶來(lái)更高成本的文檔數(shù)量,從而達(dá)到快速搜索的目的。
組合過(guò)濾器
1、布爾過(guò)濾器
must:必須匹配
must_not:都不能匹配
should:至少有一個(gè)語(yǔ)句要匹配
GET /my_store/products/_search
{
"query" : {
"filtered" : {
"filter" : {
"bool" : {
"should" : [
{ "term" : {"price" : 20}},
{ "term" : {"productID" : "XHDK-A-1293-#fJ3"}}
],
"must_not" : {
"term" : {"price" : 30}
}
}
}
}
}
}
注意:
仍然需要一個(gè)filtered查詢將所有東西抱起來(lái)
should語(yǔ)句塊里面的兩個(gè)term過(guò)濾器與bool過(guò)濾器是父子關(guān)系,需要匹配其一
2、嵌套布爾過(guò)濾器
GET /my_store/products/_search
{
"query" : {
"filtered" : {
"filter" : {
"bool" : {
"should" : [
{ "term" : {"productID" : "KDKE-B-9947-#kL5"}},
{ "bool" : {
"must" : [
{ "term" : {"productID" : "JODL-X-1937-#pV7"}},
{ "term" : {"price" : 30}} (2)
]
}}
]
}
}
}
}
}
term和bool過(guò)濾器是兄弟關(guān)系時(shí),返回的文檔至少必須匹配其中一個(gè)過(guò)濾器的條件。
查找多個(gè)精確值
GET /my_store/products/_search
{
"query" : {
"constant_score" : {
"filter" : {
"terms" : {
"price" : [20, 30]
}
}
}
}
}
包含,而不是相等
例如使用過(guò)濾器{ "term" : { "tags" : "search" } }會(huì)得到以下文檔
{ "tags" : ["search"] }
{ "tags" : ["search", "open_source"] }
term工作原理:es會(huì)在倒排索引中茶盅包括某term的所有文檔,然后構(gòu)造一個(gè)bitset。
| Token | DocIDs |
|---|---|
| open_source | 2 |
| search | 1,2 |
因此匹配到兩個(gè)文檔
精確相等
如果一定要做到精確相等,最好的方法時(shí)增加并索引另一個(gè)字段,存儲(chǔ)該字段包含詞項(xiàng)的數(shù)量
{ "tags" : ["search"], "tag_count" : 1 }
{ "tags" : ["search", "open_source"], "tag_count" : 2 }
之后構(gòu)造constant_score查詢
GET /my_index/my_type/_search
{
"query": {
"constant_score" : {
"filter" : {
"bool" : {
"must" : [
{ "term" : { "tags" : "search" } }, (1)
{ "term" : { "tag_count" : 1 } } (2)
]
}
}
}
}
}
范圍
GET /my_store/products/_search
{
"query" : {
"constant_score" : {
"filter" : {
"range" : {
"price" : {
"gte" : 20,
"lt" : 40
}
}
}
}
}
}
日期范圍
"range" : {
"timestamp" : {
"gt" : "2014-01-01 00:00:00",
"lt" : "2014-01-07 00:00:00"
}
}
支持日期計(jì)算
"range" : {
"timestamp" : {
"gt" : "now-1h"
}
}
||后面跟著數(shù)學(xué)表達(dá)式
"range" : {
"timestamp" : {
"gt" : "2014-01-01 00:00:00",
"lt" : "2014-01-01 00:00:00||+1M" (1)
}
}
字符串范圍
字典順序和字母順序
"range" : {
"title" : {
"gte" : "a",
"lt" : "b"
}
}
數(shù)字和日期字段的索引方式使得范圍計(jì)算很高校
字符串的范圍計(jì)算實(shí)際上是在為范圍內(nèi)的每個(gè)詞項(xiàng)都執(zhí)行term過(guò)濾器,唯一詞項(xiàng)越多字符串范圍計(jì)算越慢
處理Null值
null,[]和[null]所有這些都是等價(jià)的,無(wú)法存入倒排索引中
GET /my_index/posts/_search
{
"query" : {
"constant_score" : {
"filter" : {
"exists" : { "field" : "tags" }
}
}
}
}
GET /my_index/posts/_search
{
"query" : {
"constant_score" : {
"filter": {
"missing" : { "field" : "tags" }
}
}
}
}
null代表的意思:一種是被置為null,另一種是沒(méi)有值
設(shè)置映射時(shí)可以為之設(shè)置空值,用以處理顯式null值的情況(仍然不會(huì)存入倒排索引)
關(guān)于緩存
bitset是以增量的方式更新的。
一個(gè)bitsets是獨(dú)立與它所屬搜索請(qǐng)求其他部分的,一旦被緩存,bitset可以被用作多個(gè)搜索請(qǐng)求
早期的es默認(rèn)是緩存已切可以緩存的對(duì)象,這就意味著系統(tǒng)緩存bitsets太富侵略性,從而給清理緩存帶來(lái)性能壓力。
倒排索引非常快,但是絕大多數(shù)查詢組件卻很少使用它,例如term過(guò)濾字段user_id。
上百萬(wàn)用戶,每個(gè)用戶ID出現(xiàn)的概率都很小。那么使用bitsets就不是很合算,因?yàn)榫彺娴慕Y(jié)果很可能在重用之前就被剔除了
為了解決這個(gè)問(wèn)題,es會(huì)基于使用頻次自動(dòng)緩存查詢。
一個(gè)非評(píng)分查詢?cè)谧罱?56次查詢中被使用過(guò)(次數(shù)取決于查詢類型),那么這個(gè)查詢就會(huì)作為緩存的候選。
只有那些文檔數(shù)量超過(guò)10000或者超過(guò)總文檔數(shù)量的3%才會(huì)緩存bitset。
一旦被緩存了,非評(píng)分計(jì)算的bitset會(huì)一直駐留在緩存中,直到它被剔除(LRU)