Error message here!

Hide Error message here!

忘记密码?

Error message here!

请输入正确邮箱

Hide Error message here!

密码丢失?请输入您的电子邮件地址。您将收到一个重设密码链接。

Error message here!

返回登录

Close

基于MongoDB.Driver的扩展

lex-wu 2019-02-19 10:08:00 阅读数:215 评论数:0 点赞数:0 收藏数:0

由于MongoDB.Driver中的Find方法也支持表达式写法,结合

【通用查询设计思想】这篇文章中的查询思想,个人基于MongoDB扩展了一些常用的方法。

首先我们从常用的查询开始,由于MongoDB.Driver支持类似于AutoMapper返回的指定属性(Project方法),所以这里都是基于泛型的扩展///

///同步查询指定条件的数据,并且返回指定类型TDto/// /// 查询实体 /// 返回类型 /// /// public static IFindFluent FindSync(this IMongoCollection source, IQueryquery)where TEntity : class{var projection = GetTDtoReturnProperties();var expression = query?.GenerateExpression();if (null ==expression) {var emptyExpression = Builders.Filter.Empty;return source.Find(emptyExpression).Project(projection); }return source.Find(expression).Project(projection); } /// ///获取指定的返回列/// /// /// /// private static ProjectionDefinition GetTDtoReturnProperties()where TEntity : class{var returnType = typeof(TDto);var fieldList = new List>();foreach (var property inreturnType.GetProperties()) { fieldList.Add(Builders.Projection.Include(property.Name)); }return Builders.Projection.Combine(fieldList); }

这里主要是利用了IQuery接口中的GenerateExpression方法,如果前端传来了查询参数,则拼装返回我们的表达式,如果没有,默认返回一个空的Filter,再通过Project映射关系到TDto上。

排序功能:///

///排序方法/// /// /// /// /// /// public static IFindFluent Sort(this IFindFluentsource, ISortInfo sortInfo)where TEntity : class{var sort = Builders.Sort; SortDefinition sortDefinition = null;if (sortInfo != null) {if (!string.IsNullOrWhiteSpace(sortInfo.Order) && !string.IsNullOrWhiteSpace(sortInfo.Field)) {if (sortInfo.Order.Contains("asc")) sortDefinition=sort.Ascending(sortInfo.Field);if (sortInfo.Order.Contains("desc")) sortDefinition=sort.Descending(sortInfo.Field); } }returnsource.Sort(sortDefinition); }

这里前端是使用了LayUI的表格,所以API中的参数是Order和Field,我们也可以结合例如JQuery的DataTable或者其他框架的表格,只是参数SortInfo稍微不一样,大家结合实际情况来更改业务即可。

 

分页功能:///

///查询指定条件的数据/// /// 查询的实体 /// 返回的类型 /// /// 查询条件 /// 分页信息 public static async Task> ToPageResultAsync(this IMongoCollection source, IQueryquery, IPageInfo page)where TEntity : class{var pageIndex = Math.Max(0, page.PageIndex);var pageSize = Math.Max(1, page.PageSize);var cursor = source.FindSync(query);var pageResult = new PageResult{ PageIndex=pageIndex, PageSize=pageSize, TotalCount= (int)awaitcursor.CountDocumentsAsync(), Data= await cursor.Skip(pageSize /* (pageIndex - 1)).Limit(pageSize).Sort(page).ToListAsync() };returnpageResult; }

  增和删暂时不写了,官方API也提供了批处理的接口,都可以直接用的。

来看一下我们这几个扩展方法的应用(基于aspnet core)public classMongoHelper {private static readonly string DbName = ConfigHelper.GetSetting("MongoDb").ToString();private static readonly string ConnStr = ConfigHelper.GetSetting("MongoDbConnStr").ToString();private static IMongoDatabase Db { get; }private static readonly object LockHelper = new object();/#region cotr staticMongoHelper() {if (Db == null) {lock(LockHelper) {if (Db == null) {var client = newMongoClient(ConnStr); Db=client.GetDatabase(DbName); } } } }/#endregion /#region query ///

///查询一个集合中的所有数据 其集合的名称为T的名称/// /// 该集合数据的所属类型 /// 返回类型 /// 返回一个Result /// public static async Task> QueryAsync(IQuery query, string collectionName = "")where TEntity : class{//检查是否存在该文档 var existed = await CollectionExists(Db, string.IsNullOrWhiteSpace(collectionName) ?DbName : collectionName);if(existed) {var collection = Db.GetCollection(string.IsNullOrWhiteSpace(collectionName) ?DbName : collectionName);var result = collection.FindSync(query);var listResult = awaitresult.ToListAsync();returnResult.FromData(listResult.FirstOrDefault()); }else{return new Result{ Code=ResultCode.NoSuchCollection }; } }/// ///查询一个集合中的所有数据 其集合的名称为T的名称/// /// 该集合数据的所属类型 /// 返回数据类型 /// 返回一个List列表 public static async Task>> QueryListAsync(IQuery query, string collectionName = "")where TEntity : class{var collection = Db.GetCollection(string.IsNullOrWhiteSpace(collectionName) ?DbName : collectionName);var result = collection.FindSync(query);var listResult = awaitresult.ToListAsync();returnResult.FromData(listResult); }/// ///分页方法/// /// /// /// 指定文档名称 /// /// public static async Task> QueryPageResultAsync(PageQuery query, string collectionName = "")where TEntity : class{//检查是否存在该文档 var existed = await CollectionExists(Db, string.IsNullOrWhiteSpace(collectionName) ?DbName : collectionName);if(existed) {var collection = Db.GetCollection(string.IsNullOrWhiteSpace(collectionName) ?DbName : collectionName);return await collection.ToPageResultAsync(query, query); }else{return new PageResult{ Code=ResultCode.NoSuchCollection }; } }/#endregion /#region Private Methods /// ///检查是否存在该文档/// /// 指定的数据库 /// 文档名称 /// private static async Task CollectionExists(IMongoDatabase database, stringcollectionName) {var options = newListCollectionsOptions { Filter= Builders.Filter.Eq("name", collectionName) };return awaitdatabase.ListCollections(options).AnyAsync(); }/#endregion}

有了这个帮助类,我们可以看一下应用层的具体应用

///

///TEntity的分页查询/// /// 查询实体 /// 返回结果 /// 查询条件 /// public async Task> GetPagedLogsAsync(PageQueryquery)where TEntity : class{return await MongoHelper.QueryPageResultAsync(query, typeof(TEntity).Name); }/// ///TEntity的查询/// /// 查询实体 /// 返回结果 /// 查询条件 /// public async Task> GetSpecifyLogAsync(IQueryquery)where TEntity : class{return await MongoHelper.QueryAsync(query, typeof(TEntity).Name); }

看一下我们Controller的调用

///

///获取指定条件的日志分页列表/// /// 查询参数 /// [HttpPost]public async Task>SearchPagedLogsAsync(LogPageQuery query) {return await _logBll.GetPagedLogsAsync(query); }/// ///获取指定条件的日志/// /// 查询参数 /// public async Task> GetLogByIdAsync(stringid) {if (string.IsNullOrWhiteSpace(id))return Result.FromCode(ResultCode.Fail);return await _logBll.GetSpecifyLogAsync(new Query(m => m.Id == newObjectId(id))); }

  我这里的例子是为了符合单一职责的设计原则,所以指定了GetLogByIdAsync这样的单一接口,如果大家喜欢单个方法满足更多功能,可以参照【通用查询设计思想】文章中的Controller写法。

让我知道你们有更好的想法!

 

版权声明
本文为[lex-wu]所创,转载请带上原文链接,感谢
https://www.cnblogs.com/lex-wu/p/10395136.html

编程之旅,人生之路,不止于编程,还有诗和远方。
阅代码原理,看框架知识,学企业实践;
赏诗词,读日记,踏人生之路,观世界之行;

支付宝红包,每日可领