Version:5.xhtml
英文原文地址:Getting startedc#
說實話,這篇文章翻譯的很糟糕。可是個人能力有限,目前只有這個水平,還望各位多指導。api
NEST 是 Elasticsearch 的一個高層級的 .NET 客戶端,可是它仍然很是接近原始的 Elasticsearch API 。NEST 中全部的請求和響應都是經過類型公開的,這使得它能夠快速地啓動和運行。服務器
在美麗的外表之下,NEST 有着一個強大的低層級的核心 - Elasticsearch.Net 。有了這個核心,NEST 才得以(向 Elasticsearch 本體服務程序)發送請求和接收響應。這個過程當中,NEST 使用和擴展了 Elasticsearch.NET 的許多類型。另外,NEST 公開了這個低級客戶端,你能夠經過 .LowLevel 屬性來訪問。異步
鏈接位於 http://localhost:9200
的本地 Elasticsearch 是很是簡單的,你只須要實例化一個客戶端的實例便可。async
var client = new ElasticClient();
一般狀況下,你會須要向客戶端傳遞一些額外的配置選項。好比:你的 Elasticsearch 在遠程服務器上運行,那你就須要傳遞它的具體地址。 ConnectionSettings
參數就是來接收這些配置信息的,有了它你就能夠根據不一樣的配置實例化出相應的客戶端。elasticsearch
var settings = new ConnectionSettings(new Uri("http://example.com:9200")) .DefaultIndex("people"); var client = new ElasticClient(settings);
仔細看上面這個例子,咱們設置了一個默認索引。若是請求中沒有明確提供其餘索引,而且沒法從 POCO 泛型參數中推斷出索引,就會使用這個默認索引。ConnectionSettings
繼承自 ConnnectionConfiguraion
,Elasticsearch.NET (那個低層級的客戶端)經過這個對象來接收額外的配置選項。瞭解更多的配置選項,請訪問 Configuration options 。ide
注意,若是沒有配置默認索引,而 NEST 又沒法從請求中推斷出索引,那它就會拋出一個異常。函數
ConnectionSettings
沒有嚴格要求只能向 Elasticsearch 傳遞一個地址。NEST 中還提供了幾種不一樣類型的鏈接池用來配置客戶端。下面的栗子使用了一個 SniffingConnectionPool
,它包含了集羣中 3 個 Elasticsearch 節點的地址。客戶端將使用這種鏈接池來維護一個集羣中可用節點的列表,這樣即可以用循環的方式發送請求。佈局
var uris = new[] { new Uri("http://localhost:9200"), new Uri("http://localhost:9201"), new Uri("http://localhost:9202"), }; var connectionPool = new SniffingConnectionPool(uris); var settings = new ConnectionSettings(connectionPool) .DefaultIndex("people"); var client = new ElasticClient(settings);
將客戶端配置好並鏈接上 Elasticsearch 以後,咱們須要往集羣裏存儲一些數據。
假設咱們有以下簡單傳統CLR對象(Plain Old CLR Object)
public class Person { public int Id { get; set; } public string FirstName { get; set; } public string LastName { get; set; } }
使用同步或者異步的方式索引一個 POCO 實例
var person = new Person { Id = 1, FirstName = "Martijn", LastName = "Laarman" }; var indexResponse = client.Index(person); (1) var asyncIndexResponse = await client.IndexAsync(person); (2)
(1) 同步方法返回一個 IIndexResponse
對象
(2) 異步方法返回一個可等待的 Task<IIndexResponse>
對象
注意:NEST 中全部的方法都提供了同步和異步兩種版本,異步方法使用 *Async 後綴命名
上述代碼會將文檔索引到 /people/person/1
。NEST 很聰明,它會根據 Person 的 CLR 類型來推斷 type
,並根據 POCO 的 Id
屬性來推斷文檔的 id
。瞭解 NEST 中推斷文檔 id
的其餘方式,請參閱 Ids inference 。ConnectionSettings
中配置的默認索引會被用來看成請求的索引名。
警告:NEST 會將 POCO 序列化爲 JSON 文檔發送給 Elasticsearch。默認狀況下,在執行序列化時,NEST 將 POCO 的屬性名轉換成駝峯式字符串。你可使用
ConnectionSettings
的.DefaultFieldNameInferrer(Func<string,string>)
方法來改變這一行爲。
咱們已經索引了一些文檔,接下來就能夠開始查詢了。
var searchResponse = client.Search<Person>(s => s .From(0) .Size(10) .Query(q => q .Match(m => m .Field(f => f.FirstName) .Query("Martijn") ) ) ); var people = searchResponse.Documents;
people
變量如今保存着名字裏包含 Martijn 的前十我的的文檔。這個查詢的搜索終端是 /people/person/_search
,其中索引名由 ConnectionSettings
中的默認索引肯定,類型名由搜索時傳遞的泛型參數 Person
肯定。
使用 .AllTypes()
能夠搜索索引內的所有類型
var searchResponse = client.Search<Person>(s => s .AllTypes() .From(0) .Size(10) .Query(q => q .Match(m => m .Field(f => f.FirstName) .Query("Martijn") ) ) );
請求中能夠提供單個或者多個索引和類型名,瞭解更多請分別參閱 Indices paths 和 Document paths 。
到目前爲止,全部的搜索示例都使用了 NEST 的 Fluent API ,它使用 lambda 表達式構造結構化的查詢,這一點模仿了 Elasticsearch 中的 Query DSL 的查詢結構。
NEST 還公開了一個對象初始值設定語法,對於那些不熱衷於深層嵌套子表達式的開發者,能夠用這種方式來構造查詢(佈局是關鍵 ~)
這裏有個和以前的栗子相同的查詢,不過改爲了使用對象初始值設定語法來構造查詢
var searchRequest = new SearchRequest<Person>(Nest.Indices.All, Types.All) (1) { From = 0, Size = 10, Query = new MatchQuery { Field = Infer.Field<Person>(f => f.FirstName), Query = "Martijn" } }; var searchResponse = await client.SearchAsync<Person>(searchRequest);
(1) 全部的索引和類型,都在構造函數中指定
筆記:本文開始的時候提到過,高層客戶端經過
.LowLevel
屬性公開了Elasticsearch.NET
的低層客戶端。有些狀況下,低層客戶端會更合適。例如:你已經有了一個 JSON 對象,想直接發送給服務器,而不但願再把它轉換成 Fluent API 或者 Object Initializer 語法。又或者說,高層客戶端有一個 bug,讓你不得不選擇低層客戶端。使用低層客戶端,能夠經過發送字符串或者匿名類型的請求來完成工做。經過
.LowLevel
來使用低層客戶端,你可使用 NEST 中全部的強類型和序列化功能這裏有個示例:
var searchResponse = client.LowLevel.Search<SearchResponse<Person>>("people", "person", new { from = 0, size = 10, query = new { match = new { field = "firstName", query = "Martijn" } } }); var responseJson = searchResponse.Body;能夠看到,請求是一個匿名類型,可是響應體是 NEST 返回的響應類型的具體實現。
除告終構化和非結構化的查詢,Elasticsearch 還支持聚合數據
var searchResponse = await client.SearchAsync<Person>(s => s .Size(0) .Query(q => q .Match(m => m .Field(f => f.FirstName) .Query("Martijn") ) ) .Aggregations(a => a .Terms("last_names", ta => ta .Field(f => f.LastName) ) ) ); var termsAggregation = searchResponse.Aggs.Terms("last_names");
這個例子裏,match
查詢搜索出了名字裏有 "Martijn" 的人,這和以前的例子是同樣的,不一樣的是:
0
,由於咱們不須要查到的前 10 份文檔,咱們只對聚合結果感興趣terms
聚合,從而將搜索結果按照姓氏分組termsAggregation
能夠用於獲取每一個桶的文檔數量,其中每一個桶的鍵是姓氏。更多信息,請參閱 Writing aggregations