大家好,我是Edison。
上一篇:
寫在開頭
在.NET套用中整合ES一般涉及兩個方面:
(1)將ES當儲存用,類似於MongoDB,做文件的增刪查改,這一類操作偏CRUD。
(2)對ES中的數據做查詢分析,聚合統計、分組等等,這一類操作偏查詢分析。
上一篇我們了解了CRUD,我們今天再來搞定查詢和聚合作為本系列的結尾!
增加模型
為了進行今天的查詢和聚合,我們在上一篇的demo計畫中增加一個Product模型。都是常規欄位,就不再解釋了。
public classProduct : ElasticModelBase
{
publicstring Ean { get; set; }
publicstring Name { get; set; }
publicstring Description { get; set; }
publicstring Brand { get; set; }
publicstring Category { get; set; }
publicdecimal Price { get; set; }
publicint Quantity { get; set; }
public DateTime ReleaseDate { get; set; }
}
與此同時,新增一個ProductRepository:
public class ProductRepository : ElasticRepositoryBase<Product>, IProductRepository
{
public ProductRepository(IElasticProxy elasticProxy) : base(elasticProxy)
{
}
protected override string IndexName => "products";
}
分頁查詢
我們在上一篇的demo計畫中其實已經做了分頁查詢的基礎實作了:
publicvirtualasync Task<Tuple<int, IList<T>>> QueryAsync(int page, int limit)
{
var query = awaitthis.Client.SearchAsync<T>(x => x.Index(this.IndexName)
.From((page -1) * limit)
.Size(limit));
returnnew Tuple<int, IList<T>>(Convert.ToInt32(query.Total), query.Documents.ToList());
}
但很多時候我們還想要根據某個欄位排序,我們可以在上一篇的基礎類別的基礎上重寫一下,在ProductRepository就可以實作:
public override async Task<Tuple<int, IList<Product>>> QueryAsync(int page, int limit)
{
var query = awaitthis.Client.SearchAsync<Product>(x => x.Index(this.IndexName)
.From((page - 1) * limit)
.Size(limit)
.Sort(x => x.Descending(v => v.ReleaseDate)));
returnnew Tuple<int, IList<Product>>(Convert.ToInt32(query.Total), query.Documents.ToList());
}
條件查詢(基於Term)
我們在之前的學習中學習了結構化搜尋主要是透過Term來進行查詢,那麽假如我們想要根據EAN欄位來查詢某個product,則可以在ProductRepository中新增一個方法來實作:
publicasync Task<IList<Product>> QueryByEanAsync(string ean)
{
var result = awaitthis.Client.SearchAsync<Product>(x => x.Index(this.IndexName)
.Query(q => q.Term(p => p.Ean, ean)));
return result.Documents.ToList();
}
一般來說,Query的結果預設是document集合。
這裏我們測試結果如下:
那麽,如果是多條件查詢呢?比如:根據一個key查詢EAN或Name,這就是多個Term的Or查詢:
publicasync Task<IList<Product>> QueryByEanOrNameAsync(string key)
{
var result = awaitthis.Client.SearchAsync<Product>(x => x.Index(this.IndexName)
.Query(q => q.Term(p => p.Ean, key) || q.Term(p => p.Name, key)));
return result.Documents.ToList();
}
比如:根據一個key查詢Name並只篩選 Status="Active"的product ,這就是多個Term的And查詢 :
publicasync Task<IList<Product>> GetActiveProductsByNameAsync(string key)
{
var result = awaitthis.Client.SearchAsync<Product>(x => x.Index(this.IndexName)
.Query(q => q.Term(p => p.Name, key) && q.Term(p => p.Status, "Active")));
return result.Documents.ToList();
}
聚合統計
我們在之前的學習中學習了聚合查詢,那麽這裏我們透過聚合來統計一下Product數據中Price欄位的最大值、最小值和平均值:
publicasync Task<Nest.AggregateDictionary> QueryPriceAggAsync()
{
var searchResult = awaitthis.Client.SearchAsync<Product>(x => x.Index(this.IndexName)
.Size(0) // 代表不返回源數據
.Aggregations(agg => agg.Average("price_avg", avg => avg.Field("price"))
.Max("price_max", max => max.Field("price"))
.Min("price_min", min => min.Field("price")))
);
return searchResult.Aggregations;
}
聚合分組
如果我們想要根據某個欄位分組查詢product數據,那麽可以使用聚合分組:
publicasync Task<Nest.AggregateDictionary> QueryBrandAggAsync()
{
var searchResult = awaitthis.Client.SearchAsync<Product>(x => x.Index(this.IndexName)
.Size(0) // 代表不返回源數據
.Aggregations(agg => agg.Terms("brandgroup", group => group.Field("brand"))
));
return searchResult.Aggregations;
}
小結
本篇,我們了解了如何在ASP.NET 6套用中 對ES中的數據進行查詢 和 聚合,透過使用這些查詢我們可以在套用中實作一些報表功能 。
到此,本系列的學習之旅就要跟大家說聲再見了,12篇說多不多,持續輸出就是堅持,希望對你學習ElasticSearch有所幫助。
源碼
Github: https://github.com/Coder-EdisonZhou/ElasticSamples
參考資料
部落格園,包子wxl,【ElasticSearch使用系列-.NET6對接ES】:https://www.cnblogs.com/wei325/p/15881650.html
CSDN,阿星Plus,【.NET Core下使用ES】:
https://blog.csdn.net/meowv/article/details/108613494
CSDN,風神.NET,【如何在ASP.NET Core中整合ES】:https://blog.csdn.net/WuLex/article/details/123354106
極客時間,阮一鳴,【ElasticSearch核心技術與實戰】
年終總結:
數位化轉型:
C#刷題:
.NET面試:
.NET大會: