C# NEST Elasticsearch 复杂连表查询示例

以下是一个 C# NEST Elasticsearch 复杂连表查询示例:

首先,假设有两个索引 `orders` 和 `products`,其中 `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_name`、`category` 和 `description` 三个字段。查询结果将会按照 `order_id` 和 `product_id` 字段分组,并包含每个订单中所有商品的详细信息。

在以上代码中,还定义了两个实体类 `Order` 和 `Product`,分别表示 `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 索引中的所有文档:

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

在上述代码中,使用 `ElasticsearchClientWrapper` 类的 `Search` 方法查询索引,并传递 C# 类型 `MyDocument` 作为泛型参数。`Search` 方法将返回一个包含 `MyDocument` 类型的文档列表。

© 版权声明

☆ END ☆
喜欢就点个赞吧
点赞0 分享
图片正在生成中,请稍后...