Version:5.xhtml
英文原文地址:Writing queriesjson
將數據索引到了 Elasticsearch 以後,就能夠準備搜索它們了。Elasticsearch 提供了一個強大的查詢 DSL ,使得用戶能夠定義個性化的搜索邏輯。這個 DSL 是基於 JSON 的,NEST 提供了 Fluent API 和 Object Initializer 語法來實現 DSL 。c#
最簡單的查詢應該就是 match_all
了,這種查詢會返回全部的文檔,並給每份文檔的 _score
統一賦值爲 1.0
api
匹配的文檔並非都會在一次響應中所有返回,默認狀況下只返回前十份。你可使用
from
和size
來將結果分頁緩存
var searchResponse = client.Search<Project>(s => s .Query(q => q .MatchAll() ) );
上面的請求會被序列化成下面這個 JSON 對象elasticsearch
{ "query": { "match_all": {} } }
因爲 match_all
查詢很常見,所以前面的栗子有一個簡單的寫法,兩種方式序列化的結果是同樣的ide
searchResponse = client.Search<Project>(s => s .MatchAll() );
前面的兩個栗子都是使用 Fluent API 來描述查詢。NEST 還公開了一種 Object Initializer 語法去構造查詢性能
var searchRequest = new SearchRequest<Project> { Query = new MatchAllQuery() }; searchResponse = client.Search<Project>(searchRequest);
search request 有一些可用的參數,你能夠參閱 search 以得到詳細的信息。ui
默認狀況下,文檔會根據 _score
降序返回。每一個命中的 _score
是根據文檔和查詢條件的匹配程度計算的關聯分數。數字越大,表示越符合查詢條件。code
NEST 提供了許多搜索查詢,它們都記錄在 Query DSL 參考部分。在這裏,咱們要強調用戶常常執行的三類查詢操做
結構化搜索是指,查詢具備固定結構的數據。日期、時間和數字都是結構化的,查詢這些類型的字段一般是爲了查找準確的匹配項、某個範圍內的值等等。文本也能夠結構化,好比博客裏使用的關鍵字標籤。
經過結構化搜索,查詢的答案老是 「是」 或者 「否」。也就是說,文檔要麼匹配查詢,要麼就不匹配。
術語級別的查詢一般用於結構化搜索。下面的栗子查找開始日期在指定範圍內的文檔
var searchResponse = client.Search<Project>(s => s .Query(q => q .DateRange(r => r .Field(f => f.StartedOn) .GreaterThanOrEquals(new DateTime(2017, 01, 01)) .LessThan(new DateTime(2018, 01, 01)) ) ) );
(1) 查找開始於 2017 年的全部的 Project
會生成如下查詢 JSON
{ "query": { "range": { "startedOn": { "lt": "2018-01-01T00:00:00", "gte": "2017-01-01T00:00:00" } } } }
由於這個查詢的答案只有 yes
和 no
兩種狀況,我天然就不須要給查詢計分了。爲此,咱們能夠把這個查詢包裝在一個 bool
查詢 filter
子句中,這樣就可讓查詢在篩選上下文中執行
searchResponse = client.Search<Project>(s => s .Query(q => q .Bool(b => b .Filter(bf => bf .DateRange(r => r .Field(f => f.StartedOn) .GreaterThanOrEquals(new DateTime(2017, 01, 01)) .LessThan(new DateTime(2018, 01, 01)) ) ) ) ) );
{ "query": { "bool": { "filter": [ { "range": { "startedOn": { "lt": "2018-01-01T00:00:00", "gte": "2017-01-01T00:00:00" } } } ] } } }
在篩選上下文中執行查詢的好處是,Elasticsearch 能夠放棄計算相關性分數,還能夠緩存篩選器從而得到更快的後續性能
重要:術語級別的查詢沒有分析階段,也就是說不會分析查詢的輸入,進而在反向索引中尋找輸入的精確匹配。若是一個字段在索引時進行了分析,那麼再經過術語級別查詢多半會失敗。
當字段僅用於精確匹配時,應當考慮將其映射爲
keyword
類型。若是字段既用於精確匹配,又用於全文搜索,則應考慮將其映射爲multi fields
。
另外一個常見的用例是,在全文字段中搜索以查找最相關的文檔。
全文查詢用於非結構化的搜索。在這裏,咱們使用 match
查詢來查找開發人員的名字中包含 「Russ」 的全部文檔
var searchResponse = client.Search<Project>(s => s .Query(q => q .Match(m => m .Field(f => f.LeadDeveloper.FirstName) .Query("Russ") ) ) );
會生成如下查詢 JSON
{ "query": { "match": { "leadDeveloper.firstName": { "query": "Russ" } } } }
重要:全文查詢有分析階段。也就是說要分析查詢輸入,而後將分析後產生的術語和反向索引中的術語進行比較。
經過在映射期間給字段設置分析器,你能夠徹底控制索引和搜索階段的分析過程。
一個很是常見的狀況是,將不一樣的查詢組合在一塊兒造成一個複合查詢。其中最多見的是 bool
查詢
var searchResponse = client.Search<Project>(s => s .Query(q => q .Bool(b => b .Must(mu => mu .Match(m => m (1) .Field(f => f.LeadDeveloper.FirstName) .Query("Russ") ), mu => mu .Match(m => m (2) .Field(f => f.LeadDeveloper.LastName) .Query("Cam") ) ) .Filter(fi => fi .DateRange(r => r .Field(f => f.StartedOn) .GreaterThanOrEquals(new DateTime(2017, 01, 01)) .LessThan(new DateTime(2018, 01, 01)) (3) ) ) ) ) );
(1) 匹配開發人員的名字包含 Russ
的全部文檔
(2) ... 而且開發人員的姓氏包含 Cam
(3) ... 而且項目開始於 2017
會生成如下查詢 JSON
{ "query": { "bool": { "must": [ { "match": { "leadDeveloper.firstName": { "query": "Russ" } } }, { "match": { "leadDeveloper.lastName": { "query": "Cam" } } } ], "filter": [ { "range": { "startedOn": { "lt": "2018-01-01T00:00:00", "gte": "2017-01-01T00:00:00" } } } ] } } }
一份文檔必須知足三個查詢纔算匹配成功
match
查詢有助於計算出相關性分數,由於它們都在查詢上下文中執行range
查詢是在篩選上下文中執行的,索引沒有爲匹配的文檔計算分數(針對這個查詢的全部文檔具備相同的分數 1.0
)因爲 bool
查詢很是常見,所以 NEST 在查詢上重載了運算符,以使得 bool
查詢的形式更加簡潔。前面的 bool
查詢能夠更加簡潔地表示爲
searchResponse = client.Search<Project>(s => s .Query(q => q .Match(m => m .Field(f => f.LeadDeveloper.FirstName) .Query("Russ") ) && q .Match(m => m .Field(f => f.LeadDeveloper.LastName) .Query("Cam") ) && +q .DateRange(r => r .Field(f => f.StartedOn) .GreaterThanOrEquals(new DateTime(2017, 01, 01)) .LessThan(new DateTime(2018, 01, 01)) ) ) );
查看 writing bool
queries ,瞭解有關 bool
查詢的更多詳細信息和示例
搜索查詢返回的響應是一個 ISearchResponse<T>
對象,其中 T
是在調用搜索方法時傳入的泛型參數類型。響應對象有幾個屬性,其中你最可能使用的是 .Documents
,咱們將在下面演示。
獲取匹配搜索查詢的文檔是至關簡單的
var searchResponse = client.Search<Project>(s => s .Query(q => q .MatchAll() ) ); var projects = searchResponse.Documents;
.Documents
是對下面這段邏輯的一個方便的速記
searchResponse.HitsMetaData.Hits.Select(h => h.Source);
而且能夠從命中集合中檢索有關每一個命中的其餘元數據。下面的示例在使用 highlighting
時檢索命中的突出顯示
var highlights = searchResponse.HitsMetaData.Hits.Select(h => h .Highlights );