在花了很多时间研究学习了MongoDB数据库的相关知识,以及利用C#对MongoDB数据库的封装、测试应用后,决定花一些时间来总结一下最近的研究心得,把这个数据库的应用单独做为一个系列来介绍,但愿从各个方面来总结并记录一下这个新型、看似神秘的数据库使用过程。本文是这个系列的开篇,主要介绍一些MongoDB数据库的基础知识、安装过程、基础使用等方面。git
MongoDB是一款由C++编写的高性能、开源、无模式的经常使用非关系型数据库产品,是非关系数据库当中功能最丰富、最像关系数据库的数据库。它扩展了关系型数据库的众多功能,例如:辅助索引、范围查询、排序等。 程序员
MongoDB主要解决的是海量数据的访问效率问题,它做为分布式数据崛起后,使用较多的一款非结构数据库,必然有其值得称道之处,它的主要功能特性以下:github
1)面向集合的存储,适合存储对象及JSON形式的数据。
2)动态查询,MongoDB支持丰富的查询表达式。查询指令使用JSON形式的标记,可轻易查询文档中内嵌的对象及数组。
3)完整的索引支持,包括文档内嵌对象及数组。MongoDB的查询优化器会分析查询表达式,并生成一个高效的查询计划。
4)查询监视,MongoDB包含一个监视工具用于分析数据库操做的性能。
5)复制及自动故障转移,MongoDB数据库支持服务器之间的数据复制,支持主-从模式及服务器之间的相互复制。复制的主要目标是提供冗余及自动故障转移。
6)高效的传统存储方式,支持二进制数据及大型对象(如图片或视频)。
7)自动分片以支持云级别的伸缩性,自动分片功能支持水平的数据库集群,可动态添加额外的机器。 正则表达式
MongoDB数据库有几个简单的概念须要了解一下。sql
1)MongoDB中的 database
有着和咱们熟知的"数据库"同样的概念 (对 Oracle 来讲就是 schema)。一个 MongoDB 实例中,能够有零个或多个数据库,每一个都做为一个高等容器,用于存储数据。mongodb
2)数据库中能够有零个或多个 collections
(集合)。集合和传统意义上的 table 基本一致,能够简单的把二者当作是同样的东西。数据库
3)集合是由零个或多个 documents
(文档)组成。一样,一个文档能够当作是一 row
。数组
4)文档是由零个或多个 fields
(字段)组成。,对应的就是关系数据库的 columns
。缓存
5)Indexes
(索引)在 MongoDB 中扮演着和它们在 RDBMS 中同样的角色,都是为了提升查询的效率。服务器
6)Cursors
(游标)和上面的五个概念都不同,可是它很是重要,而且常常被忽视,其中最重要的你要理解的一点是,游标是当你问 MongoDB 拿数据的时候,它会给你返回一个结果集的指针而不是真正的数据,这个指针咱们叫它游标,咱们能够拿游标作咱们想作的任何事情,好比说计数或者跨行之类的,而无需把真正的数据拖下来,在真正的数据上操做。
它们的对比关系图以下所示。
数据在Mongodb里面都是以Json格式方式进行存储的,以下所示是其中的一个记录内容。
{ _id: ObjectID('4bd9e8e17cefd644108961bb'), name:'Vivek', class : '12th', subjects: [ 'physics', 'chemistry', 'math', 'english', 'computer'], address: { house_no: '12B', block: 'B', sector: 12, city : 'noida', }, grade: [ { exam: 'unit test 1', score: '60%' }, { exam: 'unit test 2', score: '70%' } ] }
在过去的很长一段时间中,关系型数据库一直是最主流的数据库解决方案,他运用真实世界中事物与关系来解释数据库中抽象的数据架构。然而,在信息技术爆炸式发展的今天,大数据已经成为了继云计算,物联网后新的技术革命,关系型数据库在处理大数据量时已经开始吃力,开发者只能经过不断地优化数据库来解决数据量的问题,但优化毕竟不是一个长期方案,因此人们提出了一种新的数据库解决方案来迎接大数据时代的到来——NoSQL(非关系型数据库),其中MongoDB数据库就是其中的NoSQL的杰出表明。在大数据时代中,大数据量的处理已经成了考量一个数据库最重要的缘由之一。而MongoDB的一个主要目标就是尽量的让数据库保持卓越的性能,这很大程度地决定了MongoDB的设计。
根据MongoDB官网的说明,MongoDB的适用场景以下:
1)网站实时数据:MongoDB很是适合实时的插入,更新与查询,并具有网站实时数据存储所需的复制及高度伸缩性。
2)数据缓存:因为性能很高,MongoDB也适合做为信息基础设施的缓存层。在系统重启以后,由MongoDB搭建的持久化缓存层能够避免下层的数据源过载。
3)大尺寸、低价值数据存储:使用传统的关系型数据库存储一些数据时可能会比较昂贵,在此以前,不少时候程序员每每会选择传统的文件进行存储。
4)高伸缩性场景:MongoDB很是适合由数十或数百台服务器组成的数据库。MongoDB的路线图中已经包含对MapReduce引擎的内置支持。
5)对象或JSON数据存储:MongoDB的BSON数据格式很是适合文档化格式的存储及查询。
MongoDB不适合使用场景以下:
1)高度事务性系统:例如银行或会计系统。传统的关系型数据库目前仍是更适用于须要大量原子性复琐事务的应用程序。
2)传统的商业智能应用:针对特定问题的BI数据库会对产生高度优化的查询方式。
3)须要复杂SQL查询的问题。
MongoDB大多数状况下,能够代替关系型数据库实现数据库业务。它更简单更直接、更快速而且一般对应用开发者的约束更少,不过缺少事务支持须要慎重考虑业务须要。
MongoDB数据的官网为:https://www.mongodb.org/,当前版本为3.2,能够直接下载安装版本在Linux或者Windows进行安装。
通常在Windows,咱们默认安装的路径为C:\Program Files\MongoDB,安装后能够手动建立一个放置数据库和日志文件的目录,通常不要放在C盘就好,以下所示:
建立文件夹d:\mongodb\data\db、d:\mongodb\data\log,分别用来安装db和日志文件,咱们之后运行数据库后,这个目录就用来放置咱们建立的数据库和日志资源了。
通常咱们安装后,为了在命令行方便调用Mongodb的命令,咱们能够设置一个全局的路径变量,以下所示。
默认状况下,mongodb的工做模式,是启动一个DOS窗口,运行mongodb的数据库服务,一旦这个DOS窗口关闭,也就中止了相关的服务,在Windows平台,咱们能够把它寄宿在Windows服务里面,让它随着系统的启动而启动,也没必要由于误关闭窗口而中止了数据库服务了。
经过下面命令行执行数据库服务的处理。
mongod --dbpath "d:\mongodb\data\db" --logpath "d:\mongodb\data\log\MongoDB.log" --install --serviceName "MongoDB"
而后使用命令行启动服务
NET START MongoDB
建立服务并顺利启动成功后,而后就能够在系统的服务列表里查看到了,咱们确认把它设置为自动启动的Windows服务便可。
启动后,咱们能够在系统【运行】里面直接使用命令mongo打开窗口就能够进行相关的操做了。
上面用了一些常见的命令操做。
而其中find方法很强大,能够组合不少条件查询的方式,以下所示:
固然还有插入更新的处理语句也是很特别的。
db.student.insert({name:'student1',subject:['arts','music']})
特别是更新操做须要说明一下,支持常规的$set方法(修改)、$unset方法(移除指定的键),还有原子级的$inc方法(数值增减),$rename方法(重命名字段名称)等等,
db.users.update({"_id" : ObjectId("51826852c75fdd1d8b805801")}, {"$set" : {"hobby" :["swimming","basketball"]}} )
db.users.update({"_id" : ObjectId("51826852c75fdd1d8b805801")},{"$unset" : {"hobby" :1 }} )
db.posts.update({"_id" : ObjectId("5180f1a991c22a72028238e4")}, {"$inc":{"pageviews":1}})
db.students.update( { _id: 1 }, { $rename: { 'nickname': 'alias', 'cell': 'mobile' } }
upsert是一种特殊的更新操做,不是一个操做符。(upsert = up[date]+[in]sert),也就是若是存在则更新,不然就写入一条新的记录操做。这个参数是个布尔类型,默认是false。
db.users.update({age :25}, {$inc :{"age" :3}}, true)
另外,Update能够对Json的集合进行处理,若是对于subject对象是一个集合的话,插入或更新其中的字段使用下面的语句
db.student.update({name:'student5'},{$set:{subject:['music']}},{upsert:true});
若是是记录已经存在,咱们可使用索引数值进行更新其中集合里面的数据,以下所示。
db.student.update({name:'student3'},{$set:{'subject.0':'arts'}});
若是咱们先在集合里面增长一个记录,而非替换的话,那么使用$push语句,以下面的语句所示。
db.student.update({name:'student3'},{$push:{'subject':'sports'}})
相反,若是要移除集合里面的某个值,使用$pop操做符,那么语句以下所示
db.student.update({name:'student3'},{$pop:{'subject':1}});
其中索引为1标识最右边的记录,-1标识为最左边的记录。
另外还可使用$pushAll
和$pullAll来增长/移除一个或多个集合记录,以下代码所示。
db.student.update({name:'student3'},{$pushAll:{'subject':['sports','craft']}}) db.student.update({name:'student3'},{$pullAll:{'subject':['sports','craft']}})
mongodb的数据库的操做仍是比较容易理解的,具体能够进一步参考官网里面的介绍。
https://docs.mongodb.org/manual/
https://docs.mongodb.org/getting-started/csharp/client/
http://mongodb.github.io/mongo-csharp-driver/2.2/
http://wiki.jikexueyuan.com/project/the-little-mongodb-book/
数据库的C#驱动使用介绍,能够参考:https://docs.mongodb.org/getting-started/csharp/,或者http://mongodb.github.io/mongo-csharp-driver/2.2/,能够下载相关的DLL而后在项目中引用,当前的驱动版本为2.2,通常引入下面几个DLL便可。
也可使用VS工具的NugGet包进行下载管理,以下所示。
而后在弹出的NugGet程序包管理界面里面搜索mongo,而后添加MongoDB.Driver的数据库驱动就可使用了。
MongoDB数据库驱动在2.2版本(或者是从2.0开始)好像彻底改写了API的接口,所以目前这个版本同时支持两个版本的API处理,一个是基于MongoDatabase的对象接口,一个是IMongoDatabase的对象接口,前者中规中矩,和咱们使用Shell里面的命令名称差很少,后者IMongoDatabase的接口是基于异步的,基本上和前者差异很大,并且接口都提供了异步的处理操做。后面我会分别对这两个部分进行详细的介绍,本文基于篇幅的缘由,介绍一下二者的简单差别就能够了。
咱们以Mongodb的数据库链接字符串mongodb://localhost/local来进行构建
1)旧接口MongoDatabase对象的构建
var client = new MongoClient(connectionString); var database = client.GetServer().GetDatabase(new MongoUrl(connectionString).DatabaseName);
2)新接口IMongoDatabase对象的构建
var client = new MongoClient(connectionString); var database = client.GetDatabase(new MongoUrl(connectionString).DatabaseName);
后者已经没有了GetServer的接口了。
3)旧接口的查找对象处理
/// <summary> /// 查询数据库,检查是否存在指定ID的对象 /// </summary> /// <param name="key">对象的ID值</param> /// <returns>存在则返回指定的对象,不然返回Null</returns> public virtual T FindByID(string id) { ArgumentValidation.CheckForEmptyString(id, "传入的对象id为空"); MongoCollection<T> collection = GetCollection(); return collection.FindOneById(new ObjectId(id)); }
3)新接口查找对象的处理
/// <summary> /// 查询数据库,检查是否存在指定ID的对象 /// </summary> /// <param name="key">对象的ID值</param> /// <returns>存在则返回指定的对象,不然返回Null</returns> public virtual T FindByID(string id) { ArgumentValidation.CheckForEmptyString(id, "传入的对象id为空"); IMongoCollection<T> collection = GetCollection(); return collection.Find(s=> s.Id == id).FirstOrDefault(); }
新接口已经没有了FindOneById等接口了,全部的操做基本上都经过Find方法进行处理。旧接口不少经过Query对象进行条件的查询,新接口又换了一个对象进行过滤条件处理了,总的来讲,两个接口差别很是大。
例如旧版本接口的Query使用C#代码以下所示:
private void TestQuery() { Query.All("name", new List<BsonValue> { BsonValue.Create("a"), BsonValue.Create("b") });//经过多个元素来匹配数组 Query.And(Query.EQ("name", "a"), Query.EQ("title", "t"));//同时知足多个条件 Query.Or(Query.EQ("name", "a"), Query.EQ("title", "t"));//知足其中一个条件 Query.EQ("name", "a");//等于 Query.Exists("type");//判断键值是否存在 Query.GT("value", 2);//大于> Query.GTE("value", 3);//大于等于>= Query.In("name", new List<BsonValue> { BsonValue.Create("a"), BsonValue.Create("b") });//包括指定的全部值,能够指定不一样类型的条件和值 Query.LT("value", 9);//小于< Query.LTE("value", 8);//小于等于<= Query.Mod("value", 3, 1);//将查询值除以第一个给定值,若余数等于第二个给定值则返回该结果 Query.NE("name", "c");//不等于 Query.Size("name", 2);//给定键的长度 Query.Type("_id", BsonType.ObjectId);//给定键的类型 Query.ElemMatch("children", Query.And( Query.EQ("name", "C3"), Query.EQ("value", "C"))); //Query.Nor(Array);//不包括数组中的值 //Query.Not("name");//元素条件语句 //Query.NotIn("name", "a", 2);//返回与数组中全部条件都不匹配的文档 //Query.Where(BsonJavaScript);//执行JavaScript //Query.Matches("Title", str);//模糊查询 至关于sql中like -- str可包含正则表达式 var keyword = "abc"; Query.Matches("Title", new BsonRegularExpression("/.*" + keyword + ".*/"));//模糊Like语法 //经过正则表达式 1开头 第二位数0~9且只能一位数,也包含20 var queryName = Query.Matches("Name", new BsonRegularExpression("Donma1([0-9]{1,1})$|20")); //查找年龄 >=10 且<=20 var queryAge = Query.And(Query.GTE("Age", 10), Query.LTE("Age", 20)); var entityQuery = Query<UserInfo>.EQ(e => e.Name, "wuhuacong"); var entityQuery2 = Query<UserInfo>.EQ(e => e.Id, "4B414D000000011613CD"); }
新版本的条件查询,则丢弃了Query这个对象,提供了FilterDefinition<T> 对象的处理,估计是这个能够处理的更好吧,同时新接口所有支持异步的处理操做了。
如插入记录的异步操做代码以下所示。
/// <summary> /// 插入指定对象到数据库中 /// </summary> /// <param name="t">指定的对象</param> public virtual async Task InsertAsync(T t) { ArgumentValidation.CheckForNullReference(t, "传入的对象t为空"); IMongoCollection<T> collection = GetCollection(); await collection.InsertOneAsync(t); }
好了,基于篇幅的缘由,把后面介绍的C#开发留到下一篇进行介绍,但愿本篇文章对你们了解mongodb数据库,以及如何在C#上面使用该数据库提供了一个简要的指引,但愿你们多多支持。