C# NEST Elasticsearch 複雜連表查詢示例

以下是一個 C# NEST Elasticsearch 複雜連表查詢示例:

首先,假設有兩個索引 ordersproducts,其中 orders 索引包含以下字段:

  • order_id:訂單 ID
  • product_id:商品 ID
  • quantity:商品數量
  • price:商品單價

products 索引包含以下字段:

  • product_id:商品 ID
  • product_name:商品名稱
  • category:商品類別
  • description:商品描述
  • price:商品單價

現在需要查詢每個訂單中包含的商品詳細信息,包括商品名稱、商品類別和商品描述。以下是一個示例代碼:

using Nest;

// 建立連接
var settings = new ConnectionSettings(new Uri("http://localhost:9200"));
var client = new ElasticClient(settings);

// 定義查詢
var searchResponse = client.Search<Order>(s => s
    .Index("orders")
    .Aggregations(a => a
        .Terms("order_agg", t => t
            .Field(f => f.OrderId)
            .Aggregations(aa => aa
                .Sum("total_quantity", sq => sq.Field(f => f.Quantity))
                .Sum("total_amount", sa => sa.Field(f => f.Price))
                .Nested("product_agg", na => na
                    .Path(p => p.Products)
                    .Aggregations(aaa => aaa
                        .Terms("product_id_agg", t => t
                            .Field(f => f.Products.ProductId)
                            .Aggregations(aaaa => aaaa
                                .TopHits("product_agg_hits", th => th
                                    .Size(int.MaxValue)
                                    .Source(s => s.Includes(i => i.Fields(f => f.ProductName, f => f.Category, f => f.Description)))
                                )
                            )
                        )
                    )
                )
            )
        )
    )
);

// 定義實體類
public class Order
{
    [JsonProperty("order_id")]
    public int OrderId { get; set; }

    [JsonProperty("product_id")]
    public int ProductId { get; set; }

    [JsonProperty("quantity")]
    public int Quantity { get; set; }

    [JsonProperty("price")]
    public decimal Price { get; set; }

    [JsonProperty("products")]
    public Product Products { get; set; }
}

public class Product
{
    [JsonProperty("product_id")]
    public int ProductId { get; set; }

    [JsonProperty("product_name")]
    public string ProductName { get; set; }

    [JsonProperty("category")]
    public string Category { get; set; }

    [JsonProperty("description")]
    public string Description { get; set; }

    [JsonProperty("price")]
    public decimal Price { get; set; }
}

在上面的代碼中,使用 Search 方法查詢 orders 索引。使用 Aggregations 方法定義聚合查詢。在聚合查詢中,使用 Terms 方法按 order_id 字段分組,並使用 Nested 方法在每個分組中嵌套查詢 products 索引。在嵌套查詢中,使用 Terms 方法按 product_id 字段分組,並使用 TopHits 方法獲取每個分組中的所有文檔,並只保留 product_namecategorydescription 三個字段。查詢結果將會按照 order_idproduct_id 字段分組,幷包含每個訂單中所有商品的詳細信息。

在以上代碼中,還定義了兩個實體類 OrderProduct,分別表示 orders 索引和 products 索引中的文檔。在 Order 類中,使用 JsonProperty 屬性將類屬性與 Elasticsearch 索引中的字段進行映射。在 Products 屬性中,使用 Product 類型表示 orders 索引中的 products 字段。在 Product 類中,同樣使用 JsonProperty 屬性將類屬性與 Elasticsearch 索引中的字段進行映射。這樣,在查詢結果中,每個訂單中的所有商品信息將會被映射到 Products 屬性中的 Product 對象中。

在 C# 中封裝 Elasticsearch API 可以簡化開發過程,提高代碼的可讀性和可維護性。以下是一個簡單的示例代碼,演示如何使用 C# 封裝 Elasticsearch API。

using System;
using System.Collections.Generic;
using System.Linq;
using Elasticsearch.Net;
using Nest;

namespace ElasticsearchWrapper
{
    public class ElasticsearchClientWrapper
    {
        private readonly ElasticClient _client;

        public ElasticsearchClientWrapper(string uri)
        {
            var node = new Uri(uri);
            var settings = new ConnectionSettings(node);
            _client = new ElasticClient(settings);
        }

        public List<T> Search<T>(string index, Func<SearchDescriptor<T>, ISearchRequest> selector = null) where T : class
        {
            var response = _client.Search<T>(s => s.Index(index).Query(q => q.MatchAll()));
            return response.Documents.ToList();
        }

        public List<T> Search<T>(string index, string query) where T : class
        {
            var searchResponse = _client.Search<T>(s => s.Index(index).Query(q => q.QueryString(qs => qs.Query(query))));
            return searchResponse.Documents.ToList();
        }

        public void Index<T>(string index, T document) where T : class
        {
            var indexResponse = _client.Index(document, i => i.Index(index));
            if (!indexResponse.IsValid)
            {
                throw new Exception(indexResponse.DebugInformation);
            }
        }

        public void DeleteIndex(string index)
        {
            var deleteIndexResponse = _client.Indices.Delete(index);
            if (!deleteIndexResponse.IsValid)
            {
                throw new Exception(deleteIndexResponse.DebugInformation);
            }
        }

        public void CreateIndex<T>(string index) where T : class
        {
            var createIndexResponse = _client.Indices.Create(index, c => c.Map<T>(m => m.AutoMap()));
            if (!createIndexResponse.IsValid)
            {
                throw new Exception(createIndexResponse.DebugInformation);
            }
        }

        public void Update<T>(string index, T document) where T : class
        {
            var updateResponse = _client.Update<T>(document.Id, u => u.Index(index).Doc(document).DocAsUpsert());
            if (!updateResponse.IsValid)
            {
                throw new Exception(updateResponse.DebugInformation);
            }
        }
    }
}

在上述代碼中,創建了一個名爲 ElasticsearchClientWrapper 的類,該類包含了一些常用的 Elasticsearch API 操作,包括索引、查詢、刪除索引、創建索引和更新文檔等。

在構造函數中,使用 ConnectionSettings 類創建一個 Elasticsearch 連接客戶端對象。在 Search 方法中,使用 SearchDescriptor 類來設置查詢參數,使用 ISearchRequest 接口來定義查詢請求。在 Index 方法中,使用 IndexResponse 類來創建索引請求,並使用 Index 方法將文檔添加到 Elasticsearch 索引中。在 DeleteIndex 方法中,使用 Indices 類來刪除 Elasticsearch 索引。在 CreateIndex 方法中,使用 Indices 類來創建 Elasticsearch 索引,並使用 Map 方法來映射 C# 類型到 Elasticsearch 索引中的字段。在 Update 方法中,使用 UpdateResponse 類來更新 Elasticsearch 索引中的文檔。

使用上述封裝後,可以在代碼中直接調用封裝好的方法,而不必再手動編寫 Elasticsearch API。例如,可以使用以下代碼查詢名爲 my_index 的 Elasticsearch 索引中的所有文檔:

var client = new ElasticsearchClientWrapper("http://localhost:9200");
var documents = client.Search<MyDocument>("my_index");

在上述代碼中,使用 ElasticsearchClientWrapper 類的 Search 方法查詢索引,並傳遞 C# 類型 MyDocument 作爲泛型參數。Search 方法將返回一個包含 MyDocument 類型的文檔列表。

來源:https://www.iwmyx.cn/cnestelasticsearchfzb.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章