MongoDB
MongoDB是一个开源的文档型数据库,由C++措辞编写,采取分布式的文件存储方案,而文件的存储格式为BSON。MongoDB支持的数据类型有很多种,如:String、Int、Float、Timestamp、Binary、Object、Date、Arrays等。而MongoDB的特点也有很多,如:强大的查询措辞、支持索引、支持自动处理碎片、支持JAVA/C#/Python等多种开拓措辞、支持面向凑集存储等。关于MongoDB的详细描述也可自行到其官网查看,我这里就不再过多啰嗦了,下面贴出与其几个干系的网址吧:
MongoDB官网:https://www.mongodb.com/

MongoDB官方的.NET API文档:http://api.mongodb.com/csharp/current/html/R_Project_CSharpDriverDocs.htm
MongoDB官方的github网址:https://github.com/mongodb/mongo
MongoDB可视化管理工具NoSQL Manager for MongoDB的官网:https://www.mongodbmanager.com/
背景
在大部分的项目中都会碰着要将短类型的数据(比如企业系统内的用户操作行为的“操作日记”数据、谈天通讯系统内的“对话记录”等数据)做持久化,而这种数据的特色便是关系大略、数据量弘大、大部分只有读写操作等。基于这些业务须要与运用处景,那么我们就可以考虑利用MongoDB来做数据的持久化存储与管理了。
在这里,我们将仿照一个基于Saas平台下的企业系统内“操作日记”的业务场景(项目将以Saas做事供应给各个企业利用,并将所有用户在系统上的操作行为以日记办法存储到数据库去),并利用MongoDB来做数据的持久化存储与管理(包含对数据的增加与查询操作)。这里我们为了简便则将代码的构造层次分为两层(实际项目中各位按需分层级),那么项目构造将是这个样子的:
1、Miidy.Web:接管来自客户真个要求,及做事端相应的出入口。由一个基于ASP.NET Core的MVC项目组成。
2、Miidy.Data:直接跟MongoDB进行通讯交互,实现对DB的增、查等操作。由一个基于.NET Core的类库组成。
业务规则:
基于上述的运用处景所悉,我们将面向的是企业客户,且因此Saas做事运行在云上的,则我们操作管理MongoDB时将面临如下几个规则(基于海量数据的读写考率):
1、希望数据能按企业ID分库,即各个企业的数据归档到其对应的独立库中。
2、能根据日期每天分表存储数据。
3、分库能按企业ID自动完成,分表能按日期自动完成。
与MongoDB通讯的API类库:
我们将利用由MongoDB官方供应的API类库来与MongoDB进行通讯与交互,在Miidy.Data项目中可通过NuGet管理器引用如下两个类库:
1、MongoDB.Bson
2、MongoDB.Driver
实当代码
通过上面的先容,我们清楚了两个分层之间的功能与关系,那么接下来我们就分别来看看它们详细的代码,及操作MongoDB的简便酷爽吧。
1、我们先看看Miidy.Data层的代码,首先定义一个名为“MongoDbContext”类,用于管理MongoDB的高下文,代码如下:
using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using System.Security.Authentication; using System.Text.RegularExpressions; using System.Threading.Tasks; using MongoDB.Bson; using MongoDB.Driver; namespace Miidy.Data.Context { /// <summary> /// MongoDB工具的高下文 /// </summary> public class MongoDbContext { /// <summary> /// Mongo高下文 /// </summary> public IMongoDatabase DbContext { get; } /// <summary> /// 初始化MongoDb数据高下文 /// 将数据库名通报进来 /// </summary> public MongoDbContext(string dbName) { //连接字符串,如:"mongodb://username:password@host:port/[DatabaseName]?ssl=true" //建议放在配置文件中 var connectionString = "mongodb://root:a123@192.168.1.6:27017"; try { var mongoClient = new MongoClient(connectionString); //数据库如果不存在,会自动创建 DbContext = mongoClient.GetDatabase(dbName); } catch (Exception e) { Log.WriteLogByError("构建MongoDbContext出错", e); throw; } } /// <summary> /// 异步获取表(凑集) /// </summary> /// <typeparam name="TEntity"></typeparam> /// <param name="datetime"></param> /// <returns></returns> public async Task<IMongoCollection<TEntity>> GetCollectionAsync<TEntity>(string tableName="") where TEntity : class { var dt = DateTime.Now.ToString("yyyy -MM-dd"); if (!string.IsNullOrEmpty(tableName)) { dt = tableName; } // 获取凑集名称,利用的标准是在实体类型名后添加日期 var collectionName = dt; // 如果凑集不存在,那么创建凑集 if (false == await IsCollectionExistsAsync<TEntity>(collectionName)) { await DbContext.CreateCollectionAsync(collectionName); } return DbContext.GetCollection<TEntity>(collectionName); } /// <summary> /// 凑集是否存在 /// </summary> /// <typeparam name="TEntity"></typeparam> /// <returns></returns> public async Task<bool> IsCollectionExistsAsync<TEntity>(string name) { var filter = new BsonDocument("name", name); // 通过凑集名称过滤 var collections = await DbContext.ListCollectionsAsync(new ListCollectionsOptions { Filter = filter }); // 检讨是否存在 return await collections.AnyAsync(); } } }
2、在Miidy.Data层增加一个名为“IMongoRepository”接口,用于封装向业务层供应操作MongoDB的操作方法,代码如下:
using System;using System.Collections.Generic;using System.Linq;using System.Linq.Expressions;using System.Text;using System.Threading.Tasks;using MongoDB.Bson;using MongoDB.Driver;namespace Miidy.Data.Interface{ public interface IMongoRepository<T> where T : class { /// <summary> /// 从指定的库与表中获取指定条件的数据 /// </summary> /// <returns></returns> Task<List<T>> GetListAsync(Expression<Func<T, bool>> predicate, string dbName, string tableName = ""); /// <summary> /// 对指定的库与表中新增数据 /// </summary> /// <returns></returns> Task<bool> Add(List<T> list, string dbName, string tableName = ""); }}
3、在Miidy.Data层再增加一个名为“MongoRepository”类,实现“IMongoRepository”接口,代码如下:
using System;using System.Collections.Generic;using System.Linq;using System.Linq.Expressions;using System.Threading.Tasks;using System.Web;using Miidy.Data.Context;using Miidy.Data.Interface;using MongoDB.Bson;using MongoDB.Driver;namespace Miidy.Data{ /// <summary> /// 封装向业务层供应操作MongoDB的操作方法 /// </summary> /// <typeparam name="T"></typeparam> public class MongoRepository<T> : IMongoRepository<T> where T : class { /// <summary> /// 从指定的库与表中获取指定条件的数据 /// </summary> /// <returns></returns> public async Task<List<T>> GetListAsync(Expression<Func<T, bool>> predicate, string dbName, string tableName) { var dbContext = new MongoDbContext(dbName); var collection = await dbContext.GetCollectionAsync<T>(tableName); return collection.AsQueryable<T>().Where(predicate).ToList(); } /// <summary> /// 对指定的库与表中新增数据 /// </summary> /// <returns></returns> public async Task<bool> Add(List<T> list, string dbName, string tableName = "") { var dbContext = new MongoDbContext(dbName); var collection = await dbContext.GetCollectionAsync<T>(tableName); await collection.InsertManyAsync(list); return true; } }}
4、在Miidy.Web层再增加一个名为“TestController”的掌握器,用于向用户供应测试读写MongoDB操作的出入口,代码如下:
using System;using System.Collections.Generic;using System.Linq;using System.Threading.Tasks;using Miidy.Core;using Miidy.Data.Interface;using Microsoft.AspNetCore.Mvc;namespace Miidy.Web.Controllers{ [Route("api/[controller]")] public class TestController : Controller { private readonly IMongoRepository<ActionLog> _IMongoRepository; public TestController(IMongoRepository<ActionLog> __IMongoRepository) { _IMongoRepository = __IMongoRepository; } /// <summary> /// 测试新增数据方法 /// </summary> /// <returns></returns> [HttpGet] public async Task<string> Add() { //创建两个不同企业ID的实体数据 var model1 = new ActionLog(); model1.CompanyId = Guid.Parse("B29BC831-A974-4114-90E2-0001E03FBCAF"); model1.ActionLogId = Guid.NewGuid(); model1.Context = "测试企业1"; model1.CreateTime = DateTime.Now; model1.UpdateTime = DateTime.Now; var model2 = new ActionLog(); model2.CompanyId = Guid.Parse("651bbe49-a4c8-4514-babb-897dad7065e3"); model2.ActionLogId = Guid.NewGuid(); model2.Context = "测试企业2"; model2.CreateTime = DateTime.Now; model2.UpdateTime = DateTime.Now; var list = new List<ActionLog>(); list.Add(model1); list.Add(model2); var group_list = list.GroupBy(p => p.CompanyId); var tableName = "ActionLog_" + DateTime.Now.ToString("yyyy-MM-dd"); foreach (var group in group_list) { var dbName = "ActionLog_" + group.FirstOrDefault().CompanyId.ToString(); await _IMongoRepository.Add(group.ToList(), dbName, tableName); } return "value1"; } /// <summary> /// 测试查询方法 /// </summary> /// <param name="companyId"></param> /// <returns></returns> [HttpGet("{companyId}")] public async Task<List<ActionLog>> Get(Guid companyId) { var dbName = "ActionLog_" + companyId.ToString(); var tableName = "ActionLog_" + DateTime.Now.ToString("yyyy-MM-dd"); var list = await _IMongoRepository.GetListAsync(p => p.Context.IndexOf("测试企业") > -1, dbName, tableName); return list; } }}
总结
1、MongoDB是开源的文档型非关系型数据库,支持JAVA/C#/Python等多种开拓措辞。
2、通过由MongoDB官方供应的两个API类库实现跟MongoDB通讯交互。
3、MongoDB不须要提前创建数据库与表构造,其会通过通报进去的数据构造自动判断是否须要掩护库与表的构造,这个机制对我们项目的大部分场景都很实用。
4、末了再通过对Miidy.Data层大略的封装后,使得面向业务层的调用非常简便。