ElasticSearch 的官方客户端 API 文档地址:https://www.elastic.co/guide/en/elasticsearch/client/index.html
ElasticSearch 的官方客户端 API 文档地址(.Net,ElasticSearch8.x):https://www.elastic.co/guide/en/elasticsearch/client/net-api/current/index.html
ElasticSearch 的官方客户端 API 文档地址(.Net,ElasticSearch7.x):https://www.elastic.co/guide/en/elasticsearch/client/net-api/7.17/index.html
我们知道,在.Net 中有Elasticsearch.Net和NEST等组件可以对 ElasticSearch 服务端进行各种操作。
但是
,但是
,但是
,由于 ElasticSearch 提供的是各类 API 接口,并且查询参数(JSON)条件会有很深的嵌套,这就导致了Elasticsearch.Net和NEST等组件在使用的时候也有很深的内嵌条件,包括各种链式操作等,如果不是老手
使用难度非常大,为了降低使用难度,Quick.ElasticSearch.Furion组件由此诞生了。
为了更好更简单的在.Net Core 中使用 ElasticSearch,特此基于NEST封装了Quick.ElasticSearch.Furion组件。
- Quick.ElasticSearch.Furion:依赖于.Net6+、Furion
Quick.ElasticSearch.Furion 包地址为:https://www.nuget.org/packages/Quick.ElasticSearch.Furion
关于 Quick.ElasticSearch.Furion 的详细使用说明,如下所示:
1、🍹 更新日志
1.0.3
调整(简化)了方法
GetModelsAll
、GetModelsAllAsync
、GetModels
、GetModelsAsync
、GetModelsFields
和GetModelsFieldsAsync
的排序参数传入方式;调整了
InsertModels
和InsertModelsAsync
方法的内部实现,判断是否有添加失败采用了Errors
属性以及ItemsWithErrors
错误对象集合;增加了
InsertModelsBatch
方法,分批添加数据,适用于大批量添加数据的情况;调整了
GetGroupValues
、GetGroupValuesAsync
、GetGroupCount
、GetGroupCountAsync
、GetGroupCountSmma
、GetGroupCountSmmaAsync
、GetGroupsCount
、GetGroupsCountAsync
、GetGroupsDate
、GetGroupsDateAsync
、GetGroupsDateSmma
、GetGroupsDateSmmaAsync
、GetGroupsDateSub
、GetGroupsDateSubAsync
、GetStatiCount
、GetStatiCountAsync
、GetStatiSumMulti
和GetStatiSumMultiAsync
方法的内部实现;调整了
AddLike
扩展方式的实现方式为 Wildcard;增加了
AddIn
条件查询扩展方法,类似 SQL 的 IN 条件;对
GetStatiSumMulti
和GetStatiSumMultiAsync
方法进行了性能优化,减少了 Http 请求次数。
1.0.2
方法
GetGroupsCount
和GetGroupsCountAsync
增加了第三个参数,以便于用户自定义返回统计数量的 Key 名称,默认为:GroupCount;增加了获取
ElasticClient
客户端对象方法:GetClient
;增加获取所有索引的方法
GetIndexs
和GetIndexsAsync
;增加了根据主键 Id 修改一个或多个字段值的方法
UpdateModelFieldsById
和UpdateModelFieldsByIdAsync
;增加了根据查询条件修改一个或多个字段值的方法
UpdateModelFieldsByCon
和UpdateModelFieldsByConAsync
;增加了根据 Id 字段获取一条数据的方法
GetModel
和GetModelAsync
;调整了
InsertModels
和InsertModelsAsync
方法的实现,由原来的Bulk(BulkAsync)
调整为了IndexMany(IndexManyAsync)
方式。
1.0.1
增加了扩展方法 CreateEsQueryModel 和 AddEsQueryModel;
重写了查询条件的使用方式;
将所有涉及到查询条件的方法都进行了调整;
简化了
GetStatiSumMulti
和GetStatiSumMultiAsync
方法所需参数的传入方式;方法
GetStatiSumMulti
和GetStatiSumMultiAsync
增加了第三个参数,错误回调方法。
1.0.0
全新组件重磅发布;
支持切换连接功能;
支持检查创建删除索引;
支持获取索引健康状态;
支持添加数据;
支持修改数据;
支持删除数据;
支持获取数据;
支持分组统计查询;
支持获取总条数、最大、最小、求和或平均值等。
2、🍟 Quick.ElasticSearch.Furion 使用说明
该组件是基于NEST
和Furion
组件进行封装使用的,目的在于结合.Net Core 更快、更简单和更灵活的使用 ElasticSearch!!!
组件使用对比:
假设我们要实现如下数据格式的统计:
[
{
"Name": "2021-01",
"Count": 100,
"Group": [
{
"Name": "碎石",
"Count": 3,
"Sum": 1000,
"Max": 100,
"Min": 10,
"Avg": 50
}
]
}
]
使用 Quick.ElasticSearch.Furion 组件的代码如下:
//获取分组统计数据(日期字段分组,并按照另一个字段进行分组,统计其条数、总和、最大值、最小值和平均值)
//统计的时间间隔维度支持的表达式有(1y:1年、1q:1季度、1M:1个月、1w:1星期、1d:1天、1h:1小时、1m:1分钟、1s:1秒钟)
//定义查询条件:(Id >= 1)
var queryCon = QuickElasticSearchExtension
//创建条件(默认创建了一个组合条件)
.CreateEsQueryModel<TestElasticSearchModel>(
EsQueryType.And,//和上一个EsQueryModel之间的连接类型(AND或OR操作,默认为AND操作)
EsQueryType.And,//当前组合查询条件集合的连接类型,针对QueryCon而言(AND或OR操作,默认为AND操作)
(queryCon) =>
{
//查询条件:(Id >= 1)
queryCon.AddGte(m => m.Id, 1);
});
//同步
var retGetGroupsDateSub = _quickElasticSearch.GetGroupsDateSub<TestElasticSearchModel>(m => m.CreateTime, m => m.UserName, m => m.UserAge, "1h", "yyyy-MM-dd HH:mm", queryCon);
//异步
var retGetGroupsDateSubAsync = await _quickElasticSearch.GetGroupsDateSubAsync<TestElasticSearchModel>(m => m.CreateTime, m => m.UserName, m => m.UserAge, "1h", "yyyy-MM-dd HH:mm", queryCon);
使用 NEST 组件的代码如下:
/// <summary>
/// 获取分组统计数据(日期字段分组,并按照另一个字段进行分组,统计其条数、总和、最大值、最小值和平均值)
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="field">要分组的字段(日期字段),格式如:m=>m.CreateTime</param>
/// <param name="fieldGroup">另一个要分组的字段,格式如:m=>m.TypeName</param>
/// <param name="fieldGroupStati">要统计总和、最大值、最小值和平均值的字段,格式如:m=>m.Price</param>
/// <param name="dateInterval">统计的日期间隔,默认为1M(支持的表达式有1y:1年、1q:1季度、1M:1个月、1w:1星期、1d:1天、1h:1小时、1m:1分钟、1s:1秒钟)</param>
/// <param name="dateFormat">统计的日期格式化方式,默认为yyyy-MM(注意大小写,完整的格式化格式为yyyy-MM-dd HH:mm:ss)</param>
/// <param name="esQueryList">动态查询条件</param>
/// <returns>返回元组对象,包含3个值,第一个为是否成功,第二个为失败的提示信息,第三个为<![CDATA[List<Dictionary<string, object>>]]>的集合,格式如:[{"Name":"2021-01","Count":100,"Group":[{"Name":"碎石","Count":3,"Sum":1000,"Max":100,"Min":10,"Avg":50}]}]</returns>
public (bool IsSucc, string ErrMsg, List<Dictionary<string, object>>? Data) GetGroupsDateSub<T>(Expression<Func<T, object>> field, Expression<Func<T, object>> fieldGroup, Expression<Func<T, object>> fieldGroupStati, string dateInterval = "1M", string dateFormat = "yyyy-MM", List<EsQueryModel<T>>? esQueryList = null) where T : class, new()
{
try
{
//查询条件
Func<QueryContainerDescriptor<T>, QueryContainer> query = q =>
{
QueryContainer ret = q;
if (esQueryList != null && esQueryList.Count > 0)
{
//组装条件为&&或||关系
for (int i = 0; i < esQueryList.Count; i++)
{
if (esQueryList[i].QueryCon.Count > 0)
{
if (i == 0)
{
ret = esQueryList[i].QueryType == EsQueryType.And ? q.Bool(b => b.Must(esQueryList[i].QueryCon)) : q.Bool(b => b.Should(esQueryList[i].QueryCon));
}
else
{
ret = esQueryList[i].PrevConType == EsQueryType.And ?
ret && (esQueryList[i].QueryType == EsQueryType.And ? q.Bool(b => b.Must(esQueryList[i].QueryCon)) : q.Bool(b => b.Should(esQueryList[i].QueryCon))) ://添加&&并且关系
ret || (esQueryList[i].QueryType == EsQueryType.And ? q.Bool(b => b.Must(esQueryList[i].QueryCon)) : q.Bool(b => b.Should(esQueryList[i].QueryCon))); //添加||或关系
}
}
}
}
return ret;
};
var ret = new List<Dictionary<string, object>>();
var response = _client.Search<T>(s => s
.Index(GetIndexName<T>())
.Query(query)
.Aggregations(ag => ag
.DateHistogram("StatiGroup", dh => dh
.Field(field) //需要聚合分组的字段名称, 类型需要为date, 格式没有要求
.CalendarInterval(dateInterval) //时间间隔,此处设置为1个月(1y:1年、1q:1季度、1M:1个月、1w:1星期、1d:1天、1h:1小时、1m:1分钟、1s:1秒钟)
.TimeZone("+08:00") //设置时区, 这样就相当于东八区的时间
.Format(dateFormat) //返回值格式化,HH大写,不然不能区分上午、下午
.MinimumDocumentCount(0) //为空的话则填充0
.Order(HistogramOrder.KeyAscending) //根据日期字段升序排列
.Aggregations(ag => ag
.Terms("StatiGroup-1", t => t
.Field(fieldGroup)
.Size(_allConfig.MaxQueryCount)
.Order(o => o
.KeyAscending() //按照分组字段升序排序
.CountAscending()//按照统计数量升序排序
)
//统计fieldStati字段的总和、最大值、最小值和平均值
.Aggregations(ags => ags
.Sum("StatiSum", m => m.Field(fieldGroupStati)) //求和
.Max("StatiMax", m => m.Field(fieldGroupStati)) //最大值
.Min("StatiMin", m => m.Field(fieldGroupStati)) //最小值
.Average("StatiAvg", m => m.Field(fieldGroupStati)) //平均值
)
)
)
)
)
.TrackTotalHits(true)//TrackTotalHits必须设置为true,否则返回total总条数超过10000条时总是返回10000
);
if (response.IsValid)
{
//获取分组标识
var stati = response.Aggregations["StatiGroup"];
//获取分组后的集合
var statiItems = ((BucketAggregate)stati).Items;
foreach (var bucketMain in statiItems)
{
var item = (DateHistogramBucket)bucketMain;
var retGroup = new List<Dictionary<string, object>>();
foreach (var bucket in ((Nest.BucketAggregate)(item.Values.ToList()[0])).Items)
{
var obj = (KeyedBucket<Object>)bucket;
retGroup.Add(new Dictionary<string, object> {
{ "Name",obj.Key.ToString()!},
{ "Count",obj.DocCount??0},
{ "Sum",IsNotNull(obj.AverageBucket("StatiSum").Value)? ToDouble2Dec(obj.AverageBucket("StatiSum").Value!):0},
{ "Max",IsNotNull(obj.AverageBucket("StatiMax").Value)? ToDouble2Dec(obj.AverageBucket("StatiMax").Value!):0},
{ "Min",IsNotNull(obj.AverageBucket("StatiMin").Value)? ToDouble2Dec(obj.AverageBucket("StatiMin").Value!):0},
{ "Avg",IsNotNull(obj.AverageBucket("StatiAvg").Value)? ToDouble2Dec(obj.AverageBucket("StatiAvg").Value!):0},
});
}
ret.Add(new Dictionary<string, object>
{
{ "Name",item.KeyAsString},
{ "Count",item.DocCount??0},
{ "Group",retGroup}
});
}
}
return (response.IsValid, !response.IsValid ? response.DebugInformation : string.Empty, ret);
}
catch (Exception ex)
{
return (false, ex.Message, null);
}
}
由此可见,NEST 使用的复杂程度,更不用说 ElasticSearch.Net 了。
功能说明:
根据配置文件读取 ElasticSearch 连接的各个配置(如:ElasticSearch 服务地址、账号和密码等);
支持配置多个 ElasticSearch 的连接配置;
支持动态切换 ElasticSearch 的连接配置;
支持检查创建删除索引;
支持获取索引健康状态;
支持添加数据(单条、多条);
支持修改数据(单条、多条);
支持删除数据(根据 Id 删除、根据条件删除);
支持获取数据(获取所有数据、获取所有满足条件的数据、获取所有满足条件并返回指定字段的数据、根据 Id 获取一条数据、获取分页的数据、获取分页并返回指定字段的数据);
支持分组统计查询(统计单字段并返回该字段所有统计值、统计单字段并返回该字段所有统计值及对应的数量、统计单段并返回另一个字段的总和最大值最小值和平均值、统计多个字段并返回多个字段对应的值以及对应分组的数据数量、按月统计并返回每个月及其数量、获取分组统计数据【日期字段分组,支持按年、季度、月份、星期、天、小时、分、秒等维度进行统计】、获取分组统计数据【日期字段分组,按月统计,并返回另一个字段的总和、最大值、最小值和平均值】、获取分组统计数据【日期字段分组,并返回另一个字段的总和、最大值、最小值和平均值】、获取分组统计数据【日期字段分组,按某年 1~12 月统计每个月的某个字段每个月的总和以及这一年的总和】、获取分组统计数据【日期字段分组,按月统计,并按照另一个字段进行分组,统计其条数、总和、最大值、最小值和平均值】、获取分组统计数据【日期字段分组,并按照另一个字段进行分组,统计其条数、总和、最大值、最小值和平均值】);
支持获取总条数、最大、最小、求和或平均值等(获取符合条件的数据总条数、获取某字段的最大值最小值求和平均值和总数等、获取某些字段相加的多个总和)。
3、🍖 安装
安装命令如下所示:
Install-Package Quick.ElasticSearch.Furion
该组件的命名空间为:Quick.ElasticSearch
。
4、🧀 配置
4.1、🥞 配置appsettings.json
在appsettings.json
配置文件中创建节点QuickElasticSearch
>MaxQueryCount
和QuickElasticSearchConfigs
,MaxQueryCount 为 ElasticSearch 索引查询的最大条数(ElasticSearch 内部默认为 10000),QuickElasticSearchConfigs 为数组类型(即可配置多个 ElasticSearch 服务地址),具体配置如下所示:
{
"QuickElasticSearch": {
"MaxQueryCount": 2000000000,
"QuickElasticSearchConfigs": [
{
"Default": true,
"ConnId": 1,
"DefaultIndex": "",
"UserName": "elastic",
"Password": "123456",
"Uri": ["http://192.168.3.200:9200/"]
}
]
}
}
配置说明:
4.2、🍞 实体特性
我们为实体提供了QuickElasticSearchConfig
特性,起作用是设置该实体的索引名称
和主键字段
,如下所示就是我们定义的一个实体对象:
using Nest;
namespace Quick.ElasticSearch.TestFurion
{
[QuickElasticSearchConfig(indexName: "test_index", primaryKey: "Id")]
public class TestElasticSearchModel
{
public long Id { get; set; }
[Keyword]
public string UserType { get; set; }
public int UserId { get; set; }
[Keyword]
public string UserName { get; set; }
public int UserAge { get; set; }
public float Money { get; set; }
public float MoneyOth { get; set; }
public DateTime CreateTime { get; set; }
}
}
说明:
indexName:索引名称;
primaryKey:主键名称。
4.3、🥐 配置 Program.cs
由于我们使用的是Furion,因此,我们可在程序启动文件中配置如下代码(具体可参考Furion 入门指南),目的是注册ElasticSearch 服务。
说明:上述的关键点就在于调用.AddElasticSearch()或者.AddElasticSearch<T>()方法对服务进行注册。
4.4、🍝 获取依赖注入对象
定义IQuickElasticSearch
对象(依赖注入方式):
public partial class FrmMain : Form
{
//定义IQuickElasticSearch对象
private readonly IQuickElasticSearch _quickElasticSearch;
public FrmMain(IQuickElasticSearch quickElasticSearch)
{
InitializeComponent();
//设置IQuickElasticSearch对象
_quickElasticSearch = quickElasticSearch;
}
}
5、🥪 具体使用
5.1、📮 获取 ElasticSearch 客户端
使用示例:
_quickElasticSearch.GetClient();
5.2、🌮 切换连接
使用示例:
_quickElasticSearch.ChangeConn(2);
5.3、🌯 获取检查创建删除索引
使用示例(获取所有索引):
//同步
var retGetIndexs = _quickElasticSearch.GetIndexs();
//异步
var retGetIndexsAsync = await _quickElasticSearch.GetIndexsAsync();
使用示例(检查索引是否存在):
//同步
var retIndexIsExist = _quickElasticSearch.IndexIsExist();
//异步
var retIndexIsExistAsync = await _quickElasticSearch.IndexIsExistAsync();
使用示例(创建索引):
//同步
var retCreateIndex = _quickElasticSearch.CreateIndex<TestElasticSearchModel>();
//异步
var retCreateIndexAsync = await _quickElasticSearch.CreateIndexAsync<TestElasticSearchModel>();
使用示例(删除索引):
//同步
var retDeleteIndex = _quickElasticSearch.DeleteIndex();
//异步
var retDeleteIndexAsync = await _quickElasticSearch.DeleteIndexAsync();
5.4、🥙 获取索引健康状态
使用示例(获取索引健康状态):
//同步
var retGetHealthStatus = _quickElasticSearch.GetHealthStatus();
//异步
var retGetHealthStatusAsyncc = await _quickElasticSearch.GetHealthStatusAsync();
5.5、🧆 添加数据
使用示例(添加数据-单条):
var rand = new Random(Guid.NewGuid().GetHashCode());
var testData = new TestElasticSearchModel
{
Id = YitIdHelper.NextId(),
UserId = rand.Next(1, 9999),
UserName = "Quber",
UserAge = rand.Next(20, 80),
Money = (float)1.429,
MoneyOth = (float)2.556,
CreateTime = DateTime.Now
};
var testDataAsync = new TestElasticSearchModel
{
Id = YitIdHelper.NextId(),
UserId = rand.Next(1, 9999),
UserName = "Jack",
UserAge = rand.Next(20, 80),
Money = (float)1.429,
MoneyOth = (float)2.556,
CreateTime = DateTime.Now
};
//同步
var retInsertModel = _quickElasticSearch.InsertModel(testData);
//异步
var retInsertModelAsync = await _quickElasticSearch.InsertModelAsync(testDataAsync);
使用示例(添加数据-多条):
var testDatas = new List<TestElasticSearchModel>
{
new TestElasticSearchModel(),
new TestElasticSearchModel()
};
//同步
var retInsertModels = _quickElasticSearch.InsertModels(testDatas, (errList, errMsg, allList) =>
{
var thisErrList = errList;
var thisErrMsg = errMsg;
});
//异步
var retInsertModelsAsync = await _quickElasticSearch.InsertModelsAsync(testDatas, async (errList, errMsg, allList) =>
{
var thisErrList = errList;
var thisErrMsg = errMsg;
await Task.CompletedTask;
});
使用示例(添加数据-多条,分批次):
var testDatas = new List<TestElasticSearchModel>
{
new TestElasticSearchModel(),
new TestElasticSearchModel()
};
var retInsertModelsBatch = _quickElasticSearch.InsertModelsBatch(testDatas, (errList, errMsg, allList) =>
{
var thisErrList = errList;
var thisErrMsg = errMsg;
},
//每批次添加的数据条数
1000,
//集群繁忙,报429错误码的时候,等待多久进行重试
"5s",
//重试次数
2);
5.6、🥗 修改数据
使用示例(修改数据-根据主键 Id 修改一个或多个字段的值):
//类似SQL:UPDATE A SET col1=123,col2=456 WHERE Id=1
//同步
var retUpdateModelFieldById = _quickElasticSearch.UpdateModelFieldsById<TestElasticSearchModel>(342235158519882, new { UserAge = 32, Money = 66.66 });
//异步
var retUpdateModelFieldByIdAsync = await _quickElasticSearch.UpdateModelFieldsByIdAsync<TestElasticSearchModel>(342235158519882, new { UserAge = 32, Money = 66.66 });
使用示例(修改数据-根据查询条件修改一个或多个字段的值):
//类似SQL:UPDATE A SET col1=123,col2=456 WHERE (Id=1 OR Id=2)
//定义查询条件:(Id = 342235158519882 OR Id = 342235158519883)
var queryCon = QuickElasticSearchExtension
//创建条件(默认创建了一个组合条件)
.CreateEsQueryModel<TestElasticSearchModel>(
EsQueryType.And,
EsQueryType.Or,
(queryCon) =>
{
//查询条件:(Id = 342235158519882 OR Id = 342235158519883)
queryCon
.AddEqu(m => m.Id, 342235158519882)
.AddEqu(m => m.Id, 342235158519883);
});
//异步
var retUpdateModelFieldsByCon = _quickElasticSearch.UpdateModelFieldsByCon<TestElasticSearchModel>(queryCon, new { UserAge = 13, Money = 996.33 });
//同步
var retUpdateModelFieldsByConAsync = await _quickElasticSearch.UpdateModelFieldsByConAsync<TestElasticSearchModel>(queryCon, new { UserAge = 14, Money = 997.44 });
使用示例(修改数据-单条):
var rand = new Random(Guid.NewGuid().GetHashCode());
var testData = new TestElasticSearchModel
{
Id = 1,
UserId = rand.Next(1, 9999),
UserName = "Quber1",
UserAge = rand.Next(20, 80),
Money = (float)2.429,
MoneyOth = (float)3.556,
CreateTime = DateTime.Now
};
var testDataAsync = new TestElasticSearchModel
{
Id = 3,
UserId = rand.Next(1, 9999),
UserName = "Jack1",
UserAge = rand.Next(20, 80),
Money = (float)2.429,
MoneyOth = (float)3.556,
CreateTime = DateTime.Now
};
//同步
var retUpdateModel = _quickElasticSearch.UpdateModel(testData);
//异步
var retUpdateModelAsync = await _quickElasticSearch.UpdateModelAsync(testDataAsync);
使用示例(修改数据-多条):
var rand = new Random(Guid.NewGuid().GetHashCode());
var testDatas = new List<TestElasticSearchModel>
{
new TestElasticSearchModel
{
Id = 1,
UserId = rand.Next(1, 9999),
UserName = "Quber1",
UserAge = rand.Next(20, 80),
Money = (float)2.429,
MoneyOth = (float)3.556,
CreateTime = DateTime.Now
},
new TestElasticSearchModel
{
Id = 3,
UserId = rand.Next(1, 9999),
UserName = "Jack1",
UserAge = rand.Next(20, 80),
Money = (float)2.429,
MoneyOth = (float)3.556,
CreateTime = DateTime.Now
},
new TestElasticSearchModel
{
Id = 4,
UserId = rand.Next(1, 9999),
UserName = "Jack1",
UserAge = rand.Next(20, 80),
Money = (float)2.429,
MoneyOth = (float)3.556,
CreateTime = DateTime.Now
}
};
//同步
var retUpdateModels = _quickElasticSearch.UpdateModels(testDatas, (errList, errMsg, allList) =>
{
var thisErrList = errList;
var thisErrMsg = errMsg;
});
//异步
var retUpdateModelsAsync = await _quickElasticSearch.UpdateModelsAsync(testDatas, async (errList, errMsg, allList) =>
{
var thisErrList = errList;
var thisErrMsg = errMsg;
await Task.CompletedTask;
});
5.7、🥘 删除数据
使用示例(删除数据-根据 Id):
//同步
var retDeleteModel = _quickElasticSearch.DeleteModel<TestElasticSearchModel>(340504986927178);
//异步
var retDeleteModelAsync = await _quickElasticSearch.DeleteModelAsync<TestElasticSearchModel>(340504986927176);
使用示例(删除数据-根据条件):
//定义查询条件:(Id >= 340506710462542 AND UserAge <= 60) OR (Id = 340506710462539 OR Id = 340506710462538)
var queryCon = QuickElasticSearchExtension
//创建条件(默认创建了一个组合条件)
.CreateEsQueryModel<TestElasticSearchModel>(
EsQueryType.And,//和上一个EsQueryModel之间的连接类型(AND或OR操作,默认为AND操作)
EsQueryType.And,//当前组合查询条件集合的连接类型,针对QueryCon而言(AND或OR操作,默认为AND操作)
(queryCon) =>
{
//查询条件:(Id >= 340506710462542 AND UserAge <= 60)
queryCon
.AddGte(m => m.Id, 340506710462542)
.AddLte(m => m.UserAge, 60);
})
//添加另一个组合条件
.AddEsQueryModel(
EsQueryType.Or,//和上一个EsQueryModel之间的连接类型(AND或OR操作,默认为AND操作)
EsQueryType.Or,//当前组合查询条件集合的连接类型,针对QueryCon而言(AND或OR操作,默认为AND操作)
(queryCon) =>
{
//查询条件:(Id = 340506710462539 OR Id = 340506710462538)
queryCon
.AddEqu(m => m.Id, 340506710462539)
.AddEqu(m => m.Id, 340506710462538);
});
//同步
var retDeleteModelBy = _quickElasticSearch.DeleteModelBy<TestElasticSearchModel>(queryCon);
//异步
var retDeleteModelByAsync = await _quickElasticSearch.DeleteModelByAsync<TestElasticSearchModel>(queryCon);
5.8、🍲 获取数据
使用示例(获取所有数据):
使用示例(获取匹配条件的所有数据):
使用示例(获取匹配条件的所有数据(返回指定字段的值)):
使用示例(获取一条数据-根据主键 Id 查询):
使用示例(获取一条数据-根据某字段查询):
使用示例(获取分页数据):
使用示例(获取分页数据-返回指定字段的值):
5.9、🥣 分组统计查询
使用示例(单个字段分组,并返回该字段的所有值集合):
使用示例(单个字段分组,并返回该字段的所有值和数量集合):
使用示例(单个字段分组,并返回另一个字段的总和、最大值、最小值和平均值):
使用示例(多个字段分组,并返回多个字段对应的值以及对应分组的数据数量):
使用示例(日期字段分组,按月统计):
使用示例(日期字段分组,支持按年、季度、月份、星期、天、小时、分、秒等维度进行统计):
使用示例(日期字段分组,按月统计,并返回另一个字段的总和、最大值、最小值和平均值):
使用示例(日期字段分组,并返回另一个字段的总和、最大值、最小值和平均值):
使用示例(日期字段分组,按某年 1~12 月统计每个月的某个字段每个月的总和以及这一年的总和):
使用示例(日期字段分组,按月统计,并按照另一个字段进行分组,统计其条数、总和、最大值、最小值和平均值):
使用示例(日期字段分组,并按照另一个字段进行分组,统计其条数、总和、最大值、最小值和平均值):
5.10、🍝 获取总条数、最大、最小、求和或平均值等
使用示例(获取符合条件的数据总条数):
使用示例(获取某字段的最大值、最小值、求和、平均值和总数等):
使用示例(获取某些字段相加的多个总和):
6、💎 Quick.ElasticSearch.Furion 方法
首先通过依赖注入在构造函数中得到IQuickElasticSearch
的实例,具体可参照上述文档中的相关示例。
6.1、📔 依赖注入方法
6.2、💸 获取 ElasticSearch 客户端
6.3、📕 切换连接方法
6.4、📗 获取检查创建删除索引方法
6.5、📘 获取索引健康状态方法
6.6、📙 添加数据方法
6.7、📚 修改数据方法
6.8、📓 删除数据方法
6.9、📒 获取数据方法
6.10、📋 分组统计查询方法
6.11、📜 获取总条数、最大、最小、求和或平均值等方法
6.12、💰 查询条件
在上面的方法中,基本都涉及到了关于查询条件(List<EsQueryModel<T>>? esQueryList = null)的参数,在此专门对查询条件的使用进行说明。
创建查询条件:
我们使用QuickElasticSearchExtension.CreateEsQueryModel<T>
静态方法来创建一个查询条件集合对象,如下所示:
//创建查询条件集合对象
//CreateEsQueryModel方法需要传入泛型T,第一个参数代表和上一个EsQueryModel之间的连接类型(AND或OR操作,默认为AND操作)、第二个参数代表当前组合查询条件集合的连接类型,针对QueryCon而言(AND或OR操作,默认为AND操作)、第三个参数代表当前组合查询条件的回调函数,用于添加具体条件
//下述代表的是创建了一个查询条件集合对象queryCon,并且设置了该对象第一个集合中的2个查询条件,类似SQL:(Id >= 340506710462542 AND UserAge <= 60)
var queryCon = QuickElasticSearchExtension
//创建条件(默认创建了一个组合条件)
.CreateEsQueryModel<TestElasticSearchModel>(
EsQueryType.And,//和上一个EsQueryModel之间的连接类型(AND或OR操作,默认为AND操作)
EsQueryType.And,//当前组合查询条件集合的连接类型,针对QueryCon而言(AND或OR操作,默认为AND操作)
(queryCon) =>
{
//查询条件:(Id >= 340506710462542 AND UserAge <= 60)
queryCon
.AddGte(m => m.Id, 340506710462542)
.AddLte(m => m.UserAge, 60);
});
组合条件:
上述的例子,我们只声明了一个组合条件,如果需要多个组合条件一起使用,则直接调用AddEsQueryModel
方法继续添加组合条件即可(该方法为上述创建的条件集合对象queryCon
的扩展方法【链式操作】),该方法的参数和CreateEsQueryModel
一模一样,如下所示的代码代表(Id 大于或等于 340506710462542 并且 UserAge 小于或等于 60) 或者(Id 等于 340506710462539 或者 Id 等于 340506710462538)
:
var queryCon = QuickElasticSearchExtension
//创建条件(默认创建了一个组合条件)
.CreateEsQueryModel<TestElasticSearchModel>(
EsQueryType.And,//和上一个EsQueryModel之间的连接类型(AND或OR操作,默认为AND操作)
EsQueryType.And,//当前组合查询条件集合的连接类型,针对QueryCon而言(AND或OR操作,默认为AND操作)
(queryCon) =>
{
//查询条件:(Id >= 340506710462542 AND UserAge <= 60)
queryCon
.AddGte(m => m.Id, 340506710462542)
.AddLte(m => m.UserAge, 60);
})
//添加另一个组合条件
.AddEsQueryModel(
EsQueryType.Or,//和上一个EsQueryModel之间的连接类型(AND或OR操作,默认为AND操作)
EsQueryType.Or,//当前组合查询条件集合的连接类型,针对QueryCon而言(AND或OR操作,默认为AND操作)
(queryCon) =>
{
//查询条件:(Id = 340506710462539 OR Id = 340506710462538)
queryCon
.AddEqu(m => m.Id, 340506710462539)
.AddEqu(m => m.Id, 340506710462538);
});
//同步
var retDeleteModelBy = _quickElasticSearch.DeleteModelBy<TestElasticSearchModel>(queryCon);
//异步
var retDeleteModelByAsync = await _quickElasticSearch.DeleteModelByAsync<TestElasticSearchModel>(queryCon);
更多条件:
如果我们想添加更多条件,直接使用方法AddEsQueryModel
追加即可,如下所示:
var queryCon = QuickElasticSearchExtension
//创建条件(默认创建了一个组合条件)
.CreateEsQueryModel<TestElasticSearchModel>(……,……,……)
//第二个组合条件
.AddEsQueryModel(……,……,……)
//第三个组合条件
.AddEsQueryModel(……,……,……)
//第四个组合条件
.AddEsQueryModel(……,……,……)
//第五个组合条件
.AddEsQueryModel(……,……,……)
//第n个组合条件
.……;
EsQueryModel 说明:
- PrevConType:和上一个 EsQueryModel 之间的连接类型(AND 或 OR 操作,默认为 AND 操作);
- QueryType:查询条件集合的连接类型,针对 QueryCon 而言(AND 或 OR 操作,默认为 AND 操作);
- QueryCon:查询条件集合。
查询条件扩展方法:
分页查询条件:
我们在使用分页方法的时候,第一个参数需要传入分页查询参数EsPagerConModel
,如下所示:
//分页条件
var pagerCon = new EsPagerConModel
{
PageIndex = 1,
PageSize = 15,
OrderField = "Id",
OrderType = "desc"
};
//定义查询条件:(Id >= 1)
var queryCon = QuickElasticSearchExtension
//创建条件(默认创建了一个组合条件)
.CreateEsQueryModel<TestElasticSearchModel>(
EsQueryType.And,//和上一个EsQueryModel之间的连接类型(AND或OR操作,默认为AND操作)
EsQueryType.And,//当前组合查询条件集合的连接类型,针对QueryCon而言(AND或OR操作,默认为AND操作)
(queryCon) =>
{
//查询条件:(Id >= 1)
queryCon.AddGte(m => m.Id, 1);
});
//同步
var retGetPager = _quickElasticSearch.GetPager<TestElasticSearchModel>(pagerCon, queryCon);
//异步
var retGetPagerAsync = await _quickElasticSearch.GetPagerAsync<TestElasticSearchModel>(pagerCon, queryCon);
EsPagerConModel 说明:
- PageIndex:当前页码(默认为 1);
- PageSize:当前页数量(默认为 15);
- OrderField:排序字段;
- OrderType:排序方式(默认为 desc)。
统计查询条件:
我们在使用GetStatiSumMulti
或GetStatiSumMultiAsync
方法获取某些字段相加的多个总和的统计的时候,第一个参数需要传入EsStatisticalSumMultiModel
,如下所示:
//类似SQL:SELECT SUM(col1)分类1,SUM(col2+col3+col4)分类2 FROM A
//统计的字段条件
var fieldCons = new List<EsStatisticalSumMultiModel>()
{
new() { AsName="分类1",Fields=new List<string>{ "Money" } },
new() { AsName="分类2",Fields=new List<string>{ "Money", "MoneyOth" } }
};
//定义查询条件:(Id >= 1)
var queryCon = QuickElasticSearchExtension
//创建条件(默认创建了一个组合条件)
.CreateEsQueryModel<TestElasticSearchModel>(
EsQueryType.And,//和上一个EsQueryModel之间的连接类型(AND或OR操作,默认为AND操作)
EsQueryType.And,//当前组合查询条件集合的连接类型,针对QueryCon而言(AND或OR操作,默认为AND操作)
(queryCon) =>
{
//查询条件:(Id >= 1)
queryCon.AddGte(m => m.Id, 1);
});
//同步
var retGetStatiSumMulti = _quickElasticSearch.GetStatiSumMulti<TestElasticSearchModel>(fieldCons, true, queryCon,
(errMsg) =>
{
var thisErrMsg = errMsg;
});
//异步
var retGetStatiSumMultiAsync = await _quickElasticSearch.GetStatiSumMultiAsync<TestElasticSearchModel>(fieldCons, true, queryCon,
async (errMsg) =>
{
var thisErrMsg = errMsg;
await Task.CompletedTask;
});
EsStatisticalSumMultiModel 说明:
- AsName(string):某几个字段相加总和最后返回的 Key 名称;
- Fields(List<string>):某几个字段相加的字段集合。