Elastcisearch.Nest 7.x 系列`僞`官方翻譯:經過 NEST 來快捷試用 Elasticsearch


Elasticsearch.Net 和 NEST 對比說明:html

  • Elasticsearch 官方爲 .NET 提供了 2 個官方客戶端庫:Elasticsearch.Net 和 NEST。
  • 能夠簡單理解爲 Elasticsearch.Net 是 NEST 的一個子集。
  • NEST 內部使用了 ElasticSearch.Net ,並經過 NEST 能夠對外暴露 ElasticSearch.Net 客戶端。
  • 但 NEST 包含了 ElasticSearch.Net 所沒有的一些高級功能,如:
    • 強類型查詢 DSL:能夠將全部請求和響應的對象類型轉換 1:1 的.NET 類型。
    • 自動轉換爲 CLR 的數據類型。

基本上 .NET 項目到了要使用上 ElasticSearch 的地步,直接選擇 NEST 便可。api

在使用 NEST 做爲客戶端的時候,建議將 ElasticClient 對象做爲單例來使用。緩存

  • ElasticClient 被設計爲線程安全。
  • ES 中的緩存是根據 ConnectionSettings 來劃分的,即服務端緩存針對的是每個 ConnectionStrings
  • 例外: 當你須要鏈接不一樣的 ES 集羣的時候,就不要用單例了,應爲不一樣的 ElasticClient 使用不一樣的 ConnectionStrings。

快速使用

  • 使用 Nest 的時候約定 Nest 版本須要跟 ElasticSearch 版本保持一致,即服務端 ES版本爲 7.3.1,則 Nest 版本也要使用 7.3.1
  • 如下示例經過 IoC 進行注入(單例),你也能夠直接經過單例模式來實現。

配置、鏈接 ElasticSearch

配置類:安全

public class ElasticSearchSettings
{
    public string ServerUri { get; set; }
    public string DefaultIndex { get; set; } = "defaultindex";
}

ElasticSearch 客戶端:異步

  • 鏈接到 ElasticSearch,並設定默認索引
public class ElasticSearchClient : IElasticSearchRepository
{
    private readonly ElasticSearchSettings _esSettings;
    private readonly ElasticClient _client;

    public ElasticSearchClient(IOptions<ElasticSearchSettings> esSettings)
    {
        _esSettings = esSettings.Value;

        var settings = new ConnectionSettings(new Uri(_esSettings.ServerUri)).DefaultIndex(_esSettings.DefaultIndex);
        _client = new ElasticClient(settings);
    }

    public ElasticSearchClient(ElasticSearchSettings esSettings)
    {
        _esSettings = esSettings;
        var settings = new ConnectionSettings(new Uri(_esSettings.ServerUri)).DefaultIndex(_esSettings.DefaultIndex);
        _client = new ElasticClient(settings);
    }
}

鏈接配置上使用密碼憑證

ElasticSearch 能夠直接在 Uri 上指定密碼,以下:elasticsearch

var uri = new Uri("http://username:password@localhost:9200")
    var settings = new ConnectionConfiguration(uri);

使用鏈接池

ConnectionSettings 不只支持單地址的鏈接方式,一樣提供了不一樣類型的鏈接池來讓你配置客戶端,如使用 SniffingConnectionPool 來鏈接集羣中的 3 個 Elasticsearch 節點,客戶端將使用該類型的鏈接池來維護集羣中的可用節點列表,並會以循環的方式發送調用請求。ide

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");

_client = new ElasticClient(settings);

NEST 教程系列 2-1 鏈接:Configuration options| 配置選項測試

索引(Indexing)

  • 這裏的「索引」需理解爲動詞,用 indexing 來理解會更好,表示將一份文檔插入到 ES 中。

假設有以下類 User.csui

public class User
{
    public Guid Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

索引(Indexing)/添加 一份文檔到 ES 中.net

//同步
var response = _client.IndexDocument<User>(new User
            {
                Id = new Guid("3a351ea1-bfc3-43df-ae12-9c89e22af144"),
                FirstName = "f1",
                LastName = "l1"
            });

//異步
var response = _client.IndexDocumentAsync<User>(new User
            {
                Id = new Guid("82f323e3-b5ec-486b-ac88-1bc5e47ec643"),
                FirstName = "f2",
                LastName = "l2"
            });
  • 目前提供的方法基本上都含有同步和異步版本(異步方法以 *Async 結尾)
  • IndexDocument 方法會判斷添加的文檔是否已經存在(根據 _id),若存在,則添加失敗。
  • NEST 會自動將 Id 屬性做爲 ES 中的 _id,更多關於 id 的推斷方式見此博文:NEST 教程系列 9-3 轉換:Id 推斷
    • 默認狀況下,會使用 camel 命名方式進行轉換,你可使用 ConnectionSettings 對象的 .DefaultFieldNameInferrer(Func<string, string>) 方法來調整默認轉換行爲,更多關於屬性的推斷的見此博文:NEST 教程系列 9-4 轉換:Field 屬性推斷

最終請求地址爲:

PUT  /users/_doc/3a351ea1-bfc3-43df-ae12-9c89e22af144

查詢

經過類 lambda 表達式進行查詢

經過 Search 方法進行查詢。

var result = _client.Search<User>(s=>s.From(0)
                .Size(10)
                .Query(q=>q.Match(m=>m.Field(f=>f.LastName).Query("l1"))));

請求 URL 以下:

POST /users/_search?typed_keys=true
  • 以上搜索是基於「users」索引來進行搜尋

如何在 ES 上的全部索引上進行搜索?經過 AllIndices(),以下:

var result = _client.Search<User>(s=>s
    .AllIndices()  //指定在全部索引上進行查詢
    .From(0)
    .Size(10)
    .Query(q=>q.Match(m=>m.Field(f=>f.LastName).Query("l1"))));

假設有以下文檔:

//users 索引
"hits" : [
      {
        "_index" : "users",
        "_type" : "_doc",
        "_id" : "3a351ea1-bfc3-43df-ae12-9c89e22af144",
        "_score" : 1.0,
        "_source" : {
          "id" : "3a351ea1-bfc3-43df-ae12-9c89e22af144",
          "firstName" : "f1",
          "lastName" : "l1"
        }
      },
      {
        "_index" : "users",
        "_type" : "_doc",
        "_id" : "05245504-053c-431a-984f-23e16d8fbbc9",
        "_score" : 1.0,
        "_source" : {
          "id" : "05245504-053c-431a-984f-23e16d8fbbc9",
          "firstName" : "f2",
          "lastName" : "l2"
        }
      }
    ]
// thirdusers 索引
"hits" : [
  {
    "_index" : "thirdusers",
    "_type" : "_doc",
    "_id" : "619ad5f8-c918-46ef-82a8-82a724ca5443",
    "_score" : 1.0,
    "_source" : {
      "firstName" : "f1",
      "lastName" : "l1"
    }
  }
]

則最終能夠獲取到 users 和 thirdusers 索引中分別獲取到 _id 爲 3a351ea1-bfc3-43df-ae12-9c89e22af144 和 619ad5f8-c918-46ef-82a8-82a724ca5443 的文檔信息。

能夠經過 .AllTypes() 和 .AllIndices() 從全部 類型(types) 和 全部 索引(index)中查詢數據,最終查詢會生成在 /_search 請求中。關於 Type 和 Index,可分別參考:NEST 教程系列 9-6 轉換:Document Paths 文檔路徑跳轉:NEST 教程系列 9-7 轉換:Indices Paths 索引路徑

經過查詢對象進行查詢

經過 SearchRequest 對象進行查詢。

例:在全部索引查詢 LastName="l1"的文檔信息

var request = new SearchRequest(Nest.Indices.All) //在全部索引上查詢
{
    From = 0,
    Size = 10,
    Query = new MatchQuery
    {
        Field = Infer.Field<User>(f => f.LastName),
        Query = "l1"
    }
};
var response = _client.Search<User>(request);

生成的請求 URL 爲:

POST  /_all/_search?typed_keys=true

經過 .LowLever 屬性來使用 Elasticsearch.Net 來進行查詢

使用 Elasticsearch.Net 來進行查詢的契機:

  • 當客戶端存在 bug,即便用上述 NEST 的 Search 和 SearchRequest 異常的時候,能夠考慮用 Elasticsearch.Net 提供的查詢方式。
  • 當你但願用一個匿名對象或者 JSON 字符串來進行查詢的時候。
var response = _client.LowLevel.Search<SearchResponse<User>>("users", PostData.Serializable(new
{
    from = 0,
    size = 10,
    query = new
    {
        match = new
        {
            lastName = "l1"
        }
    }
}));

聚合查詢

除告終構化和非結構化查詢以外, ES 一樣支持聚合(Aggregations)查詢:

var result = _client.Search<User>(s => s
    .Size(0) //設置爲 0 ,可讓結果只包含聚合的部分:即 hits 屬性中沒有結果,聚合結果顯示在 」aggregations「
    .Query(q =>
        q.Match(m =>
            m.Field(f => f.FirstName)
                .Query("f2")))
    .Aggregations(a => //使用 terms 聚合,並指定到桶 last_name 中
        a.Terms("last_name", ta =>
            ta.Field(f => f.LastName)))
    );
  • 通常使用 term 聚合來獲取每一個存儲桶的文檔數量,其中每一個桶將以 lastName 做爲關鍵字。

更多關於聚合的操做可見此:NEST 教程系列 8 聚合:Writing aggregations | 使用聚合

相關文章
相關標籤/搜索