C#MongoDB使用实践

最近项目要求做一个主要业务的操作日志,保存后供追溯查询。由于需要较高的写入性能,且不用繁琐的关系存储,思来想去nosql适合。

在比较redis和mongodb后决定采用后者,原因只有一个,后者支持方便的条件查询……

1、先说环境搭建(Windows 10),先进入官网https://www.mongodb.com/download-center?jmp=nav#community下载最新的3.2版本,是否需要with SSL看项目需求。

2、下载完成直接点击安装,安装完成后:

1):手动创建dbpath路径

2):将mongodb安装为service,以admin权限启动cmd输入命令:

mongod.exe --bind_ip 127.0.0.1 --logpath "D:\MongoDB\dbConf\mongodb.log" --logappend --dbpath "D:\MongoDB\db" --serviceName "MongoDB" --serviceDisplayName "MongoDB" --install

其中,     bind_ip:指定访问数据的主机ip,这里仅限本地;

logpath:log文件路径,自主指定;

logappend:追加形式写log;

dbpath:即上面创建好的dbpath;

serviceName:服务名称;

serviceDisplayName;显示的服务名称;

3)、启动服务:net start MongoDB

3、进入安装目录运行mongo即可打开console,常用命令:

Show dbs-------所有数据库

Use [dbname] -------进入指定数据库

Show collections-------显示所有集合(相当于tsql的table)

Db.[collectionname].find()-------查询集合所有数据

Db.[collectionname].drop()-------删除集合,如果当前只有一个集合,那么将删除db

其他命令可分别使用db.help()和db.[collectionname].help()查询

4、环境配置完毕,添加驱动,这里使用的是官方最新1.11版,可以在VisualStudio中使用NuGet工具直接添加:

  1)在NuGet中搜索mongodb,请选择第二个mongocsharpdriver;

  2)添加完毕后会多出两个dll:MongoDB.Driver.dll和MongoDB.Bson.XML;

  3)官方1.x和2.x驱动的api是不同的,要注意。

5、驱动使用方法见如下provider,由于业务层使用了泛型,这里用了比较多的判断:

using _5yue.Common;
using _5yue.Models;
using MongoDB.Bson;
using MongoDB.Driver;
using MongoDB.Driver.Builders;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _5yue.Data.MongoDB
{
    public class MongoDBProvider
    {
        private static string serverAddress = "mongodb://localhost:27017";
        private static string mongoDbName = "db_name";

        //private MongoServer server;
        private MongoClient client = null;
        private MongoDatabase database = null;
        private MongoCollection collection = null;

        public MongoDBProvider(string collectionName)
        {
            if (collection == null)
            {
                client = new MongoClient(serverAddress);// 打开连接
                database = client.GetServer().GetDatabase(mongoDbName);// 打开数据库
                collection = database.GetCollection(collectionName);// 打开集合(相当于表)
            }
            else if (!collection.Name.Equals(collectionName))
            {
                collection = database.GetCollection(collectionName);// 更换集合
            }
        }

        #region 插入
        public void InsertObj<T>(T document)// 单条
        {
            collection.Insert<T>(document);
        }
        public void InsertBson(BsonDocument bDoc)// 插入单条bson
        {
            collection.Insert(bDoc);
        }
        public void InsertObjList<T>(IList<T> objs)// 多条
        {
            collection.InsertBatch<T>(objs);
        }

        #endregion

        #region 查询
        public MongoCursor<T> GetAll<T>()
        {
            return collection.FindAllAs<T>();
        }

        /// <summary>
        /// 通过条件获取结果
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="user"></param>
        /// <param name="entityId"></param>
        /// <param name="minTime"></param>
        /// <param name="maxTime"></param>
        /// <returns></returns>
        public MongoCursor<T> GetByCondition<T>(OperateLogModel olModel)
        {
            if (olModel != null && parameterNameList != null && parameterNameList.Count > 0)
            {
                List<IMongoQuery> list = new List<IMongoQuery>();
                list.Add(Query.EQ("paras", olModel.operatorId));// paras:db中存放的字段,olModel.operatorId: 传过来的查询条件
                if (list.Count > 0)
                {
                    var query = Query.And(list);// 条件连接
                    //return collection.FindAs<T>(Query.EQ("CreaterId", 2));
                    return collection.FindAs<T>(query);
                }
                else
                {
                    return collection.FindAllAs<T>();
                }
            }
            else return null;
        }

        #endregion

        #region 工具
        public void ChangeCollection(string collectionName)
        {
            collection = database.GetCollection(collectionName);
        }

        public MongoDatabase GetDB()
        {
            return database == null ? database : null;
        }
        public MongoCollection GetCollection()
        {
            return collection == null ? collection : null;
        }

        /// <summary>
        /// 把MongoCursor转换成List类型
        /// </summary>
        /// <param name="cursor">文档游标</param>
        /// <returns></returns>
        public List<T> CursorToList<T>(MongoCursor<T> cursor)
        {
            List<T> resultList = new List<T>();
            cursor.GetEnumerator().MoveNext();// 设置游标
            if(cursor.Count() > 0)
            {
                foreach (var obj in cursor)// 遍历
                {
                    resultList.Add(obj);
                }
            }
            return resultList;
        }
        #endregion
    }
}

点击显示

6、业务类:

  

using _lbh.Models;
using _lbh.Data.MongoDB;
using MongoDB.Bson;
using MongoDB.Driver;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using _lbh.Common;

namespace _lbh.DataProvider
{
    /// <summary>
    /// 操作日志
    /// </summary>
    public class OperateLog : BaseProvider
    {
        public static MongoDBProvider mDBProvider = null;

        /// <summary>
        ///  初始化mongoDB
        /// </summary>
        /// <param name="collectionName">集合名称</param>
        public static void InitMongoDB(string collectionName)
        {
            if (mDBProvider == null)// 为空就初始化
            {
                mDBProvider = new MongoDBProvider(collectionName);
            }
            else if (!collectionName.Equals(mDBProvider.GetCollection()))// 如不是当前集合
            {
                mDBProvider.ChangeCollection(collectionName);// 修改为当前集合
            }
        }

        #region 插入
        /// <summary>
        /// 直接插入实体对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        /// <param name="collectionName"></param>
        public static void Insert<T>(T obj, string collectionName)
        {
            InitMongoDB(collectionName);
            mDBProvider.InsertObj<T>(obj);
        }

        /// <summary>
        /// 直接插入对象列表
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="objList"></param>
        /// <param name="collectionName"></param>
        public static void InsertList<T>(List<T> objList, string collectionName)
        {
            InitMongoDB(collectionName);
            mDBProvider.InsertObjList<T>(objList);
        }

        #endregion

        #region 查询
        /// <summary>
        /// 获取指定集合的所有数据,无论是否Bson形式
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="model"></param>
        /// <returns></returns>
        public static List<T> GetAll<T>(OperateLogModel model)
        {
            if (model == null || Utils.StrIsNullOrEmpty(model.collectionName))
            {
                return null;
            }
            InitMongoDB(model.collectionName);
            MongoCursor<T> result = mDBProvider.GetAll<T>();
            List<T> resultList = mDBProvider.CursorToList<T>(result);
            return resultList;
        }

        /// <summary>
        /// 指定条件查询
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="model"></param>
        /// <returns></returns>
        public static List<T> GetLByCondition<T>(OperateLogModel model)
        {
            if (model == null || Utils.StrIsNullOrEmpty(model.collectionName))
            {
                return null;
            }
            InitMongoDB(model.collectionName);
            MongoCursor<T> result = mDBProvider.GetByCondition<T>(model);// 获取查询结果
            List<T> resultList = mDBProvider.CursorToList<T>(result);// 数据结构转换
            return resultList;
        }
        #endregion
    }
}

点击显示

7、条件Model定义:

// 这是查询用的条件model

    public class OperateLogModel
    {
        /// <summary>
        /// 集合名称_集合为nosql存放数据的单位,相当于rdb的表
        /// </summary>
        public string collectionName { get; set; }
        /// <summary>
        /// 操作员id
        /// </summary>
        public int operatorId { get; set; }
        /// <summary>
        /// 操作员名称
        /// </summary>
        public string operatorName { get; set; }
        /// <summary>
        /// 实体对象id
        /// </summary>
        public string entityId { get; set; }
        /// <summary>
        /// 查询时间下限
        /// </summary>
        [BsonDateTimeOptions(Kind = DateTimeKind.Local)]
        public DateTime minTime { get; set; }
        /// <summary>
        /// 查询时间上限
        /// </summary>
        [BsonDateTimeOptions(Kind = DateTimeKind.Local)]
        public DateTime maxTime { get; set; }
    }

点击打开

8、数据实体Model定义: 略

9、业务入口调用:

  插入:OperateLog.InsertList<OrderModel>(pList, "OrderModel");

  查询:List<OrderModel> sa = OperateLog.GetLByCondition<OrderModel>(new OperateLogModel(););

10、补充:

  1)、MongoDB内部已实现了较完善的线程池,所以多数情境下不用考虑。

  2)、MongoDB存储时将日期字段转为UTC标准(即比北京时间晚8小时),需要在相关Model的时间字段添加[BsonDateTimeOptions(Kind = DateTimeKind.Local)]修饰。

  3)、使用官方驱动的弊端之一,实体Model中必须包含ObjectId _id字段,此字段将作为默认主键保存在库中。处理手段之一是使用collection.Insert(Bson bson)插入数据,Bson结果类似Json,db内部也是以此存取数据。

  4)、想到再说……

总结,本项目中只算非常入门的使用MongoDB,至于分布式存储、同步等特性还有待挖掘,本人能力有限,如有错误欢迎指正!   :)

时间: 2024-10-13 15:59:48

C#MongoDB使用实践的相关文章

MongoDB应用实践思考

最近研究MongoDB,利用其可以简单快速地搭建一套灵活的no schema存储系统. 本文通过论证和分析需求,利用MongoDB快速搭建了一套具有良好性能及可用性满足上亿规模的存储系统. 在关于NoSQL数据库的选型上,需要结合自身数据模型.访问方式以及成本等方面的考虑作一个权衡(trade off). 那么经过研究MongoDB(2.6.4版本)有如下特点: 可用性: 1.支持高可用灵活的服务集群配置,有主从.副本集.自动分片模式. 2.基于文档的查询,高性能,简单查询上万的QPS. 3.支

将Log4Net 日志保存到mongodb数据库实践

log4net的大名早有耳闻,一直没真正用过,这次开发APP项目准备在服务端使用log4net. 日志的数据量较大,频繁的写数据库容易影响系统整体性能,所以独立将日志写到mongodb数据库是不错的选择.---经过2天的摸索,总结出本文档. github有个开源项目log4mongo-net,另一位斯克迪亚作者根据开源项目又做了修改http://skyd.sinaapp.com/archives/1282. 所以直接拿斯克迪亚的代码来使用. 1.将log4net和mongodb驱动升级为最新版本

使用Kettle增量抽取MongoDB数据实践

需求: 增量抽取MongoDB数据并加载到MSSQL 由于不能使用关系型数据库的自定义SQL, 所以主要遇到的问题有: 增量时间的查询和参数控制 ETL的批次信息和调用参数的写入 第一个问题的解决如下: 使用命名参数在Query页中进行过滤, 一开始会担心${}的引用方式会用Mongo的语法冲突, 测试后发现运行正常 第二个问题: 先为结果增加常量值, 如常量值固定则直接写死, 不固定的常量值先设置为空串, 在后面使用字符串替换组件传入命名参数, 最后用字段选择把空串的常量值移除

Mongodb基础实践(二)

在前面的文章里面主要介绍了MongoDB的文档,集合,数据库等操作和对文档的增.删.改相关知识,接下来会总结一点有关查询的相关知识. 在MySQL中,我们知道数据查询是优化的主要内容,读写分离等技术都是可以用来处理数据库查询优化的,足以见数据库查询是每个系统中很重要的一部分,之前介绍了find的简单使用,下面会介绍一些相对比较复杂一点的查询. 一.数据查询 MySQL数据库中主要是用select 结合where子句实现数据的查询,功能特别强大,例如多表联合查询.支持正则表达式等.不在这里做过多的

Redis+MongoDB 最佳实践 做到读写分离 -摘自网络

方案1. (被否定) 加上Redis,做到MongoDB的读写分离,单一进程从MongoDB及时把任务同步到Redis中. 看起来很完美,但是上线后出现了各种各样的问题,列举一下: 1.Redis队列长度为多少合适? 2.同步进程根据优先级从MongoDB向Redis同步过程中,一次取多少任务合适?太大导致很多无谓的开销,太小又会频繁操作MongoDB 3.当某一个子任务处理较慢的时候,会导致MongoDB的前面优先级较高的任务没有结束,而优先级较低的确得不到处理,造成消费者空闲 最终方案: 在

mongodb数据库实践笔记

mongodb 操作规则 从网站上下载安装文件然后在安装目录下创建文件夹data和log创建配置文件mongo.config里面填充如下: ##数据文件dbpath=D:\mongodb\data##日志文件logpath=D:\mongodb\log\mongo.log##错误日志采用追加模式,配置这个选项后mongodb的日志会追加到现有的日志文件,而不是从新创建一个新文件 启动mongodb在cmd命令下启动以下命令d:cd d:\MongoDBcd bin然后输入 mongod --co

MongoDB资料汇总(转)

原文:MongoDB资料汇总 上一篇Redis资料汇总专题很受大家欢迎,这里将MongoDB的系列资料也进行了简单整理.希望能对大家有用. 最后更新时间:2013-04-22 1.MongoDB是什么 MongoDB介绍PPT分享 MongoDB GridFS介绍PPT两则 初识 MongoDB GridFS MongoDB GridFS 介绍 一个NoSQL与MongoDB的介绍PPT MongoDB:下一代MySQL? 写给Python程序员的MongoDB介绍 又一篇给Python程序员的

MongoDB基础知识(一)

互联网行业的发展非常的迅速,数据存储以及架构优化方面也有很多不同的解决方案,例如关系型数据库.非关系型数据库.数据仓库技术等.更多数据库类产品的出现,为我们很好的解决了数据存储的问题,例如Redis缓存,MySQL关系型数据库,MongoDB文档型数据库,Hbase数据仓库等. 随着业务的发展,在对架构优化时,选取了MongoDB存储一部分数据,作为一个运维人员只能迎头赶上,去学习操作和维护相关知识.下面的文档就是自己学习MongoDB数据库的学习笔记,主要有以下特点: 1.理论较少,主要是实际

十个 MongoDB 使用要点

转自:http://www.cnblogs.com/zhengyun_ustc/archive/2013/01/25/2875962.html 从 mongodb 阶段性技术总结 中抽取并整理了对大家有帮助的十个要点: 1.mongodb 表名和字段名统一用小写字母 mongodb 是默认区分大小写的,为了避免以前在 mysql 下遇到的大小写敏感导致程序访问频频出错, 建立规范,mongodb 的表名和字段名都用小写字母命名. 2.尽可能的缩短字段名的长度 mongodb 的 schema f