.NetCore操作MongDB简要代码实现

.NetCore操作MongoDB简要代码实现

MongoDB是用C++编写,基于分布式文件存储的开源的数据库(是nosql类型的数据库)。它旨在为应用提供可扩展的高性能数据库存储解决方案。Mongo将数据以文档的形式存储,它的数据结构是键值对(key-value),其中数据字段存储的不一定是基本类型(int,string,bool...)的数据,它还可以是数组,对象等。

主要概念

DataBase    -----数据库,它有自己的集合和权限。不同的数据库是分开文件存放的
Collection   -----集合,它是数据库中的文档组,它其实是没有固定结构的!但是在应用中,我们应该是将一类组织结构相同的数据存放在一个集合中。
Document  -----文档 ,一条记录就是一个文档,是一组键值对(BSON)。
Field           -----字段 ,键值对信息   
Index          -----索引 

MongoDb数据类型

String 字符串。存储数据常用的数据类型。在 MongoDB 中,UTF-8 编码的字符串才是合法的。
Integer 整型数值。用于存储数值。根据你所采用的服务器,可分为 32 位或 64 位。
Boolean 布尔值。用于存储布尔值(真/假)。
Double 双精度浮点值。用于存储浮点值。
Min/Max keys 将一个值与 BSON(二进制的 JSON)元素的最低值和最高值相对比。
Array 用于将数组或列表或多个值存储为一个键。
Timestamp 时间戳。记录文档修改或添加的具体时间。
Object 用于内嵌文档。
Null 用于创建空值。
Symbol 符号。该数据类型基本上等同于字符串类型,但不同的是,它一般用于采用特殊符号类型的语言。
Date 日期时间。用 UNIX 时间格式来存储当前日期或时间。你可以指定自己的日期时间:创建 Date 对象,传入年月日信息。
Object ID 对象 ID。用于创建文档的 ID。
Binary Data 二进制数据。用于存储二进制数据。
Code 代码类型。用于在文档中存储 JavaScript 代码。
Regular expression 正则表达式类型。用于存储正则表达式。

 

 

-------------------------------------------------------------------------

以下是.NetCore中简单使用MongoDb

引入如下程序集

MongoDB.Driver

 

简单封装MongoDB

1、封装获取集合操作

  1     public static class MongoCollectionExtension
  2     {
  3         /// <summary>
  4         /// 获取记录数
  5         /// </summary>
  6         /// <typeparam name="T"></typeparam>
  7         /// <param name="collection"></param>
  8         /// <param name="expression"></param>
  9         /// <returns></returns>
 10         public static long GetCount<T>(this IMongoCollection<T> collection, Expression<Func<T, bool>> expression) where T : BaseEntity
 11         {
 12             return collection.Find(expression).CountDocuments();
 13         }
 14         /// <summary>
 15         /// 获取记录数
 16         /// </summary>
 17         /// <typeparam name="T"></typeparam>
 18         /// <param name="collection"></param>
 19         /// <param name="expression"></param>
 20         /// <returns></returns>
 21         public static async Task<long> GetCountAsync<T>(this IMongoCollection<T> collection, Expression<Func<T, bool>> expression) where T : BaseEntity
 22         {
 23             return await collection.Find(expression).CountDocumentsAsync();
 24         }
 25         /// <summary>
 26         /// 根据Id查询
 27         /// </summary>
 28         /// <typeparam name="T"></typeparam>
 29         /// <param name="collection"></param>
 30         /// <param name="id"></param>
 31         /// <returns></returns>
 32         public static T QueryById<T>(this IMongoCollection<T> collection, string id) where T : BaseEntity
 33         {
 34             var result = collection.Find(p => p.Id == id).FirstOrDefault();
 35             return result;
 36         }
 37         /// <summary>
 38         /// 根据Id查询
 39         /// </summary>
 40         /// <typeparam name="T"></typeparam>
 41         /// <param name="collection"></param>
 42         /// <param name="id"></param>
 43         /// <returns></returns>
 44         public static async Task<T> QueryByIdAsync<T>(this IMongoCollection<T> collection, string id) where T : BaseEntity
 45         {
 46             var asyncCursor = await collection.FindAsync(p => p.Id == id);
 47             return asyncCursor.FirstOrDefault();
 48         }
 49         /// <summary>
 50         /// 查询符合条件的第一条记录
 51         /// </summary>
 52         /// <typeparam name="T"></typeparam>
 53         /// <param name="collection"></param>
 54         /// <param name="expression"></param>
 55         /// <returns></returns>
 56         public static T QueryOne<T>(this IMongoCollection<T> collection, Expression<Func<T, bool>> expression) where T : BaseEntity
 57         {
 58             var result = collection.Find(expression).FirstOrDefault();
 59             return result;
 60         }
 61         /// <summary>
 62         /// 查询符合条件的第一条记录
 63         /// </summary>
 64         /// <typeparam name="T"></typeparam>
 65         /// <param name="collection"></param>
 66         /// <param name="expression"></param>
 67         /// <returns></returns>
 68         public static async Task<T> QueryOneAsync<T>(this IMongoCollection<T> collection, Expression<Func<T, bool>> expression) where T : BaseEntity
 69         {
 70             var asyncCursor = await collection.FindAsync(expression);
 71             return asyncCursor.FirstOrDefault();
 72         }
 73         /// <summary>
 74         /// 查询符合条件的记录
 75         /// </summary>
 76         /// <typeparam name="T"></typeparam>
 77         /// <param name="collectioin"></param>
 78         /// <param name="expression"></param>
 79         /// <returns></returns>
 80         public static List<T> QueryMany<T>(this IMongoCollection<T> collectioin, Expression<Func<T, bool>> expression,FindOptions findOptions= null) where T : BaseEntity
 81         {
 82             var result = collectioin.Find(expression, findOptions).ToList();
 83             return result;
 84         }
 85         /// <summary>
 86         /// 查询符合条件的记录
 87         /// </summary>
 88         /// <typeparam name="T"></typeparam>
 89         /// <param name="collection"></param>
 90         /// <param name="expression"></param>
 91         /// <returns></returns>
 92         public static async Task<List<T>> QueryManyAsync<T>(this IMongoCollection<T> collection, Expression<Func<T, bool>> expression, FindOptions<T> findOptions=null) where T : BaseEntity
 93         {
 94             var asyncCursor = await collection.FindAsync(expression,findOptions);
 95             return asyncCursor.ToList();
 96         }
 97       
 98 
 99         /// <summary>
100         /// 根据指定条件删除
101         /// </summary>
102         /// <typeparam name="T"></typeparam>
103         /// <param name="collection"></param>
104         /// <param name="expression"></param>
105         public static void RemoveMany<T>(this IMongoCollection<T> collection, Expression<Func<T, bool>> expression) where T : BaseEntity
106         {
107             collection.DeleteMany(expression);
108         }
109         /// <summary>
110         /// 根据指定条件删除
111         /// </summary>
112         /// <typeparam name="T"></typeparam>
113         /// <param name="collection"></param>
114         /// <param name="expression"></param>
115         /// <returns></returns>
116         public static async Task RemoveManyAsync<T>(this IMongoCollection<T> collection, Expression<Func<T, bool>> expression) where T : BaseEntity
117         {
118             await collection.DeleteManyAsync(expression);
119         }
120         /// <summary>
121         /// 根据id移除
122         /// </summary>
123         /// <typeparam name="T"></typeparam>
124         /// <param name="collection"></param>
125         /// <param name="id"></param>
126         public static void RemoveById<T>(this IMongoCollection<T> collection, string id) where T : BaseEntity
127         {
128             collection.DeleteOne(p => p.Id == id);
129         }
130         /// <summary>
131         /// 根据id移除
132         /// </summary>
133         /// <typeparam name="T"></typeparam>
134         /// <param name="collection"></param>
135         /// <param name="id"></param>
136         /// <returns></returns>
137         public static async Task RemoveByIdAsync<T>(this IMongoCollection<T> collection, string id) where T : BaseEntity
138         {
139             await collection.DeleteOneAsync(p => p.Id == id);
140         }
141         /// <summary>
142         /// 移除指定记录
143         /// </summary>
144         /// <typeparam name="T"></typeparam>
145         /// <param name="collection"></param>
146         /// <param name="t"></param>
147         public static void RemoveOne<T>(this IMongoCollection<T> collection, T t) where T : BaseEntity
148         {
149             collection.DeleteOne(p => p.Id == t.Id);
150         }
151         /// <summary>
152         /// 移除指定记录
153         /// </summary>
154         /// <typeparam name="T"></typeparam>
155         /// <param name="collection"></param>
156         /// <param name="t"></param>
157         /// <returns></returns>
158         public static async Task RemoveOneAsync<T>(this IMongoCollection<T> collection, T t) where T : BaseEntity
159         {
160             await collection.DeleteOneAsync(p => p.Id == t.Id);
161         }
162         /// <summary>
163         /// 新增
164         /// </summary>
165         /// <typeparam name="T"></typeparam>
166         /// <param name="collection"></param>
167         /// <param name="t"></param>
168         /// <param name="userId"></param>
169         public static void AddOne<T>(this IMongoCollection<T> collection, T t, string userId) where T : BaseEntity
170         {
171             CompleteCreatedEntity(t, userId);
172             collection.InsertOne(t);
173         }
174         /// <summary>
175         /// 新增
176         /// </summary>
177         /// <typeparam name="T"></typeparam>
178         /// <param name="collection"></param>
179         /// <param name="t"></param>
180         /// <param name="userId"></param>
181         /// <returns></returns>
182         public static async Task AddOneAsync<T>(this IMongoCollection<T> collection, T t, string userId) where T : BaseEntity
183         {
184             CompleteCreatedEntity(t, userId);
185             await collection.InsertOneAsync(t);
186         }
187         /// <summary>
188         /// 新增多个
189         /// </summary>
190         /// <typeparam name="T"></typeparam>
191         /// <param name="collection"></param>
192         /// <param name="list"></param>
193         /// <param name="userId"></param>
194         public static void AddMany<T>(this IMongoCollection<T> collection, List<T> list, string userId) where T : BaseEntity
195         {
196             list.ForEach(p => CompleteCreatedEntity(p, userId));
197             collection.InsertMany(list);
198         }
199         /// <summary>
200         /// 新增多个
201         /// </summary>
202         /// <typeparam name="T"></typeparam>
203         /// <param name="collection"></param>
204         /// <param name="list"></param>
205         /// <param name="userId"></param>
206         /// <returns></returns>
207         public static async Task AddManyAsync<T>(this IMongoCollection<T> collection, List<T> list, string userId = "") where T : BaseEntity
208         {
209             list.ForEach(p => CompleteCreatedEntity(p, userId));
210             await collection.InsertManyAsync(list);
211         }
212         /// <summary>
213         /// 根据Id更新
214         /// </summary>
215         /// <typeparam name="T"></typeparam>
216         /// <param name="collection"></param>
217         /// <param name="updateDefinition"></param>
218         /// <param name="id"></param>
219         /// <param name="userId"></param>
220         public static void UpdateOneById<T>(this IMongoCollection<T> collection, UpdateDefinition<T> updateDefinition, string id, string userId = "") where T : BaseEntity
221         {
222             updateDefinition = updateDefinition.Set(p => p.LastModifiedUtc, DateTime.UtcNow)
223                 .Set(p => p.LastModifierId, userId);
224             collection.UpdateOne(p => p.Id == id, updateDefinition);
225         }
226         /// <summary>
227         /// 根据Id更新
228         /// </summary>
229         /// <typeparam name="T"></typeparam>
230         /// <param name="collection"></param>
231         /// <param name="updateDefinition"></param>
232         /// <param name="id"></param>
233         /// <param name="userId"></param>
234         /// <returns></returns>
235         public static async Task UpdateOneByIdAsync<T>(this IMongoCollection<T> collection, UpdateDefinition<T> updateDefinition, string id, string userId = "") where T : BaseEntity
236         {
237             updateDefinition = updateDefinition.Set(p => p.LastModifiedUtc, DateTime.UtcNow)
238                 .Set(p => p.LastModifierId, userId);
239             await collection.UpdateOneAsync(p => p.Id == id, updateDefinition);
240         }
241 
242         /// <summary>
243         /// 更新
244         /// </summary>
245         /// <typeparam name="T"></typeparam>
246         /// <param name="collection"></param>
247         /// <param name="t"></param>
248         /// <param name="userId"></param>
249         public static void UpdateEntity<T>(this IMongoCollection<T> collection, T t, string userId) where T : BaseEntity
250         {
251             t.LastModifierId = userId;
252             t.LastModifiedUtc = DateTime.UtcNow;
253             collection.ReplaceOne(p => p.Id == t.Id,t);
254         }
255         /// <summary>
256         /// 更新
257         /// </summary>
258         /// <typeparam name="T"></typeparam>
259         /// <param name="collection"></param>
260         /// <param name="t"></param>
261         /// <param name="userId"></param>
262         public static async Task UpdateEntityAsync<T>(this IMongoCollection<T> collection, T t, string userId) where T : BaseEntity
263         {
264             t.LastModifierId = userId;
265             t.LastModifiedUtc = DateTime.UtcNow;
266             var result = await collection.ReplaceOneAsync(p=>p.Id==t.Id,t);
267         }
268         /// <summary>
269         /// 根据条件更新多个
270         /// </summary>
271         /// <typeparam name="T"></typeparam>
272         /// <param name="collectioin"></param>
273         /// <param name="updateDefinition"></param>
274         /// <param name="expresion"></param>
275         /// <param name="userId"></param>
276         public static void UpdateMultiple<T>(this IMongoCollection<T> collectioin, UpdateDefinition<T> updateDefinition, Expression<Func<T, bool>> expresion, string userId = "") where T : BaseEntity
277         {
278             updateDefinition = updateDefinition.Set(p => p.LastModifiedUtc, DateTime.UtcNow)
279                .Set(p => p.LastModifierId, userId);
280             collectioin.UpdateMany(expresion, updateDefinition);
281         }
282         /// <summary>
283         /// 根据条件更新多个
284         /// </summary>
285         /// <typeparam name="T"></typeparam>
286         /// <param name="collectioin"></param>
287         /// <param name="updateDefinition"></param>
288         /// <param name="expresion"></param>
289         /// <param name="userId"></param>
290         /// <returns></returns>
291         public static async Task UpdateMultipleAsync<T>(this IMongoCollection<T> collectioin, UpdateDefinition<T> updateDefinition, Expression<Func<T, bool>> expresion, string userId = "") where T : BaseEntity
292         {
293             updateDefinition = updateDefinition.Set(p => p.LastModifiedUtc, DateTime.UtcNow)
294                .Set(p => p.LastModifierId, userId);
295             await collectioin.UpdateManyAsync(expresion, updateDefinition);
296         }
297         /// <summary>
298         /// 补全新增的数据信息
299         /// </summary>
300         /// <typeparam name="T"></typeparam>
301         /// <param name="t"></param>
302         public static void CompleteCreatedEntity<T>(T t, string userId) where T : BaseEntity
303         {
304             DateTime utcNow = DateTime.UtcNow;
305             t.CreatedUtcTime = utcNow;
306             t.LastModifiedUtc = utcNow;
307             t.CreatorId = userId;
308             t.LastModifierId = userId;
309         }
310     }

 

配置、实体类信息

MongoDbSetting:配置mongodb连接信息
 1     /// <summary>
 2     /// mongodb setting
 3     /// </summary>
 4     public class MongoDbSetting
 5     {
 6         /// <summary>
 7         /// connection string
 8         ///for example   mongodb://host1:27017,host2:27017  
 9         /// </summary>
10         public string Connection { get; set; }
11         /// <summary>
12         /// database name
13         /// </summary>
14         public string Database { get; set; }
15     }

配置信息示例

1    "MongoDbSetting": {
2      "Connection": "mongodb://localhost:27017",
3      "Database": "ProductDb"
4    }

 

BaseEntity是数据库实体的基类,用于声明一些共用的字段,以及限定数据库实体类型。

BaseEntity定义

 1     /// <summary>
 2     /// base entity
 3     /// </summary>
 4     public class BaseEntity
 5     {
 6         /// <summary>
 7         /// id
 8         /// </summary>
 9         [BsonId]
10         [BsonRepresentation(BsonType.ObjectId)]
11         public string Id { get; set; }
12         public string CreatorId { get; set; }
13         public DateTime CreatedUtcTime { get; set; }
14         public string LastModifierId { get; set; }
15         public DateTime LastModifiedUtc { get; set; }
16     }

 

Product.cs

 1     public class Product : BaseEntity
 2     {
 3         public string SKU { get; set; }
 4         public string Title { get; set; }
 5         public string ShortDescription { get; set; }
 6         public string Description { get; set; }
 7         public string DisplayName { get; set; }
 8         public string CategoryId { get; set; }
 9         public List<string> Brands { get; set; }
10         public double Price { get; set; }
11         public int Qty { get; set; }
12         public Dictionary<string, object> Attributes { get; set; }
13 
14     }
View Code

 

简单测试使用

以下是简单的service层调用,关于NetCore中对mongodb context进行注入,此处略

 1     public class ProductService : IProductService
 2     {
 3         private readonly MongoDbContext _context;
 4         public ProductService(MongoDbContext context)
 5         {
 6             this._context = context;
 7         }
 8         public async Task AddProductAsync(Product newProduct)
 9         {
10             await _context.GetCollection<Product>().AddOneAsync(newProduct,"100001");
11         }
12 
13         public async Task DeleteProductByIdAsync(string id)
14         {
15             await _context.GetCollection<Product>().RemoveByIdAsync(id);
16         }
17 
18         public async Task<Product> GetProductByIdAsync(string id)
19         {
20             return await _context.GetCollection<Product>().QueryByIdAsync(id);
21         }
22 
23         public async  Task<List<Product>> GetProductByCategoryIdAsync(string categoryId,int pageIndex,int pageSize)
24         {
25             Expression<Func<Product, bool>> expression = p => p.CategoryId == categoryId;
26             FindOptions<Product> findOptions = new FindOptions<Product>();
27             //分页
28             int skipCount = (pageIndex - 1) * pageSize;
29             findOptions.Skip = skipCount;
30             findOptions.Limit = pageSize;
31             //排序
32             var sort = Builders<Product>.Sort.Ascending(p=>p.CreatedUtcTime).Ascending(p=>p.LastModifiedUtcTime);
33             findOptions.Sort = sort;
34             return await _context.GetCollection<Product>().QueryManyAsync(expression);
35            
36         }
37 
38         public async Task UpdateProductAsync(Product product)
39         {
40             await _context.GetCollection<Product>().UpdateEntityAsync(product,"admin");
41         }
42          
43     }
View Code

 

----------------附------------------

1、对IMongoCollection进行扩展,定义符合业务的数据通用操作,当然也可以根据实际情况直接使用mongodb的net driver的原生接口操作。本文是自定义的业务规范,在调用时一般都是调用封装进行操作的。但是对于子集(内部对象(特别时一些动态数据时,例如Dictionary))的查询时,可以直接使用Builders<>.Filter指定字段进行查询。示例

 1         public async Task GetProduct(ProductSearchContract contract)
 2         {
 3             var filterBuilder = Builders<Product>.Filter;
 4             var filter = filterBuilder.Empty;
 5             if (!string.IsNullOrEmpty(contract.SKU))
 6             {
 7                 filter &= filterBuilder.Eq(p => p.SKU, contract.SKU);
 8             }
 9             if (!string.IsNullOrEmpty(contract.Model))
10             {
11                 filter &= filterBuilder.Eq("Attributes.Model", contract.Model); //
12             }
13             if (contract.ListingTimeFrom != null && contract.ListingTimeFrom.Value > DateTime.MinValue)
14             {
15                 filter &= filterBuilder.Lte("Attributes.ListingTime", contract.ListingTimeFrom.Value.Date.ToString("yyyy-MM-dd")); //
16             }
17 
18             await _context.GetCollection<Product>().FindAsync(filter);
19         }
View Code

 

2、在mongodb中Id(主键)的数据类型是ObjectId。但是在本文BaseEntity的定义中,Id使用的string类型。是因为ObjectId是mongodb定义的数据类型,它不是C#的通用类型,如果在程序中使用objectId,会导致数据类型转换或者不必要的引用。在声明时使用[BsonId][BsonRepresentation(BsonType.ObjectId)]特性。

3、在调用mongodb原生接口中,可以发现MongoDB没有对数据库连接进行open和close操作。其实mongodb driver推荐使用单例的mongodb连接,它是线程安全

4、关于mongodb的事务,在单机作为服务器的情况是不需要的(单机服务器使用mongodb事务会报错【Standalone servers do not support transactions】),只有在集群情况下才会有用。本文暂不考虑构建仓储,使用工作单元的方式(感觉mongodb没有必要做成仓储的方式,仓储-工作单元方式更多的是为关系型数据库实现事务的)。参阅mongodb的事务

5、mongdb driver操作collection,在进行数据插入时发现没有此collection则会自动创建(无需指定创建)。当collection不存在时进行查询是不会报错的,查询结果为空!

6、MongoDB是文档型数据库,对于大量数据的操作存储方面的性能较之关系型数据库优势还是比较明显的。在应用系统中日志数据(错误日志,操作日志等)还是比较庞大的,特别是随着系统运行。日志信息存放在关系型数据库中占用空间大,而且也不利于检索。所以在不少公司中用MongoDb存储系统日志信息。当然利用MongoDb存储实际业务数据的也不少的。

-------- 参考文档 ----------

https://mongodb.github.io/mongo-csharp-driver/

https://www.runoob.com/mongodb/mongodb-tutorial.html

 

  

posted on 2020-04-26 21:40  john_yong  阅读(951)  评论(0编辑  收藏  举报

导航