StructuredSearch

結(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)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容