首页 > 代码库 > MongoDB基础

MongoDB基础

下载 C# dll 

官方驱动:https://github.com/mongodb/mongo-csharp-driver/downloads。下载后,还提供了一个酷似msdn的帮助文档。

samus驱动:https://github.com/samus/mongodb-csharp/downloads。  
  [BsonId]会把int 的值,在mongodb中转为"_id" 值
  [BsonElement("boxtype")] 会把mongodb中的boxtype,对应到当下的此标记的字段
  ObjectId 会自动 “_Id” 值

 MongoClient client = new MongoClient("mongodb://127.0.0.1:2222");//MongoDB实例
            MongoCollection mc = client.GetServer().GetDatabase("test").GetCollection("person");
 
            //================【增】
            Person p1 = new Person() { Name = "aa", PhoneNumber = "110", list = new List<int>() { 1,2,3}, Address = "000", Gender = ‘男‘, Age = 125, RegTime = DateTime.Now };
            mc.Insert(p1);//.Insert() 插入
 
            Person p2 = new Person() { Name = "bb", PhoneNumber = "120", list = new List<int>() { 3,2,1 }, Address = "111", Gender = ‘男‘, Age = 25, RegTime = DateTime.Now.AddDays(3) };
            mc.Insert<Person>(p2);//.Insert<T>() 插入
 
            List<Person> listPerson = new List<Person>();
            listPerson.Add(new Person() { Name = "cc", PhoneNumber = "369", list = new List<int>() {5,8,6 }, Address = "987", Gender = ‘女‘, Age = 27, RegTime = DateTime.Now });
            listPerson.Add(new Person() { Name = "dd", PhoneNumber = "987", list = new List<int>() { 5, 8, 6 }, Address = "777", Gender = ‘女‘, Age = 26, RegTime = DateTime.Now });
 
            mc.InsertBatch(listPerson);//InsertBatch()插入,批量插入  InsertBatch<T>()一样
 
            //=================【删】
 
            //【删除全部】
            //mc.RemoveAll();
 
            //【有条件的进行删除】
            //删除 Age>100的数据
            //IMongoQuery query = Query.GT("Age", 100);
           
            //删除 RegTime大于当前时间的数据
            //IMongoQuery query = Query.GT("RegTime", DateTime.Now);
            
            //删除 Name是aa和dd的数据
            //IMongoQuery query = Query.In("Name", BsonArray.Create(new List<string>() { "aa","dd"}));
            //mc.Remove(query);
            
        
            //==================【改】
            IMongoQuery query = Query.Exists("_id");//所有数据
            IMongoUpdate update = Update.Set("Age",111111);
 
            mc.Update(query, update, UpdateFlags.Multi);// 设置UpdateFlags.Multi才能把符合条件的所有的数据都进行修改;不然只能修改第一个
           
                   //mc.save()方法,存在则修改;不存在则添加 _id来断定存在与否
            //==================【查】
            MongoCursor m = mc.FindAllAs<Person>();//获取所有
            foreach (Person p in m)
            {
                Console.WriteLine("name:" + p.Name + "Age:" + p.Age + "RegTime:" + p.RegTime + "...");
            }
 
            Person w = mc.FindOneAs<Person>();//获取一个
            Console.WriteLine("name:" + w.Name + "Age:" + w.Age + "RegTime:" + w.RegTime + "...");
 
            //【有条件进行查询】
            IMongoQuery query2 = Query.And(Query.EQ("Gender",‘男‘),Query.In("Name",BsonArray.Create(new List<string>{"aa","cc","d"})));
            MongoCursor ms =   mc.FindAs<Person>(query2);
            foreach (Person p in ms)
            {
                 Console.WriteLine("name:"+p.Name+"Age:"+p.Age+"RegTime:"+p.RegTime+"...");
            }
            Console.ReadKey();


List<MID> w2 = mc.FindAs<MID>(query).SetFields(new string[]{"Age","_id"}).ToList();
collection.FindAs<MgUserID>(query).SetFields(fd).SetSortOrder(sort).SetLimit(pageSize).SetSkip(pageSize * (pageIndex - 1)).ToList(); 

 

 

 

下载
【 https://www.mongodb.org/downloads#production 】下载MongoDB

启动

    1、启动之前,我们要给mongodb指定一个文件夹,这里取名为”db",用来存放mongodb的数据。

               技术分享
2、管理员运行cmd,首先找到mongodb的bin的路径,然后运行mongod开启命令,同时用--dbpath指定数据存放地点为“db”文件夹。 
【 mongod --dbpath=D:\Codes\MongoDB\MongoDBFolder\db  】  {自己创建的db,用来存储mongodb数据的文件夹路径;mongodb数据是存在磁盘上的,db就是mongodb的数据存储的地方}

3、最后要看下是否开启成功,从图中的信息中获知,mongodb采用27017端口,那么我们就在浏览器里面键入【 http://localhost:27017  】,提示 It looks like you are trying to access MongoDB over HTTP on the native driver port. 

基本操作

     由于是开篇,就大概的说下基本的“增删查改“,我们再开一个cmd,输入mongo命令打开shell,其实这个shell就是mongodb的客户端, 【 mongo 】

同时也是一个js的编译器,默认连接的是“test”数据库。

 

    技术分享

 

    <1>  insert 操作

             好,数据库有了,下一步就是集合,这里就取集合名为“person”,要注意的就是文档是一个json的扩展(Bson)形式。

    技术分享

  <2> find 操作

       我们将数据插入后,肯定是要find出来,不然插了也白插,这里要注意两点:

           ① “_id": 这个字段是数据库默认给我们加的GUID,目的就是保证数据的唯一性。

           ② 严格的按照Bson的形式书写文档,不过也没关系,错误提示还是很强大的。

  技术分享

 <3> update操作

      update方法的第一个参数为“查找的条件”,第二个参数为“更新的值”,学过C#,相信还是很好理解的。

  技术分享

<4> remove操作

      remove中如果不带参数将删除所有数据,呵呵,很危险的操作,在mongodb中是一个不可撤回的操作,三思而后行。

技术分享

如果此时,关闭 第一个 启动的cmd,再执行 增删改查的操作,就会报错; 127.0.0.1:27017中断链接



深入增删改查

一: Insert操作

     上一篇也说过,文档是采用“K-V”格式存储的,如果大家对JSON比较熟悉的话,我相信学mongodb是手到擒来,我们知道JSON里面Value

可能是“字符串”,可能是“数组”,又有可能是内嵌的一个JSON对象,相同的方式也适合于BSON。

      常见的插入操作也就两种形式存在:“单条插入”和“批量插入”。

   

    ①  单条插入

          先前也说了,mongo命令打开的是一个javascript shell。所以js的语法在这里面都行得通,看起来是不是很牛X。      

    技术分享

   ② 批量插入

      这玩意跟“单条插入”的差异相信大家应该知道,由于mongodb中没有提供给shell的“批量插入方法”,没关系,各个语言的driver都打通

了跟mongodb内部的批量插入方法,因为该方法是不可或缺的,如果大家非要模拟下批量插入的话,可以自己写了for循环,里面就是insert。

 

二:Find操作

     日常开发中,我们玩查询,玩的最多的也就是二类:

     ①: >, >=, <, <=, !=, =。

     ②:And,OR,In,NotIn

这些操作在mongodb里面都封装好了,下面就一一介绍:

    <1>"$gt", "$gte", "$lt", "$lte", "$ne", "没有特殊关键字",这些跟上面是一一对应的,举几个例子。

技术分享

   

<2> "无关键字“, "$or", "$in","$nin" 同样我也是举几个例子

 

技术分享

  

<3> 在mongodb中还有一个特殊的匹配,那就是“正则表达式”,这玩意威力很强的。

技术分享

 

<4> 有时查询很复杂,很蛋疼,不过没关系,mongodb给我们祭出了大招,它就是$where,为什么这么说,是因为$where中的value

  就是我们非常熟悉,非常热爱的js来助我们一马平川。

技术分享

 

三:Update操作

      更新操作无非也就两种,整体更新和局部更新,使用场合相信大家也清楚。

    <1> 整体更新

         不知道大家可还记得,我在上一篇使用update的时候,其实那种update是属于整体更新。

  技术分享

   

  <2> 局部更新

        有时候我们仅仅需要更新一个字段,而不是整体更新,那么我们该如何做呢?easy的问题,mongodb中已经给我们提供了两个

   修改器: $inc 和 $set。

   ①  $inc修改器

       $inc也就是increase的缩写,学过sql server 的同学应该很熟悉,比如我们做一个在线用户状态记录,每次修改会在原有的基础上

    自增$inc指定的值,如果“文档”中没有此key,则会创建key,下面的例子一看就懂。

技术分享

 

 ② $set修改器

      啥也不说了,直接上代码 

技术分享

 

 <3> upsert操作

     这个可是mongodb创造出来的“词”,大家还记得update方法的第一次参数是“查询条件”吗?,那么这个upsert操作就是说:如果我

没有查到,我就在数据库里面新增一条,其实这样也有好处,就是避免了我在数据库里面判断是update还是add操作,使用起来很简单

将update的第三个参数设为true即可。

技术分享

  

 <4> 批量更新

     在mongodb中如果匹配多条,默认的情况下只更新第一条,那么如果我们有需求必须批量更新,那么在mongodb中实现也是很简单

的,在update的第四个参数中设为true即可。例子就不举了。

 

四: Remove操作

      这个操作在上一篇简单的说过,这里就不赘述了。


高级操作

    今天跟大家分享一下mongodb中比较好玩的知识,主要包括:聚合,游标。

一: 聚合

      常见的聚合操作跟sql server一样,有:count,distinct,group,mapReduce。

<1> count

        count是最简单,最容易,也是最常用的聚合工具,它的使用跟我们C#里面的count使用简直一模一样。

技术分享

 

<2> distinct

       这个操作相信大家也是非常熟悉的,指定了谁,谁就不能重复,直接上图。

技术分享

 

<3> group

    在mongodb里面做group操作有点小复杂,不过大家对sql server里面的group比较熟悉的话还是一眼

能看的明白的,其实group操作本质上形成了一种“k-v”模型,就像C#中的Dictionary,好,有了这种思维,

我们来看看如何使用group。

    下面举的例子就是按照age进行group操作,value为对应age的姓名。下面对这些参数介绍一下:

       key:  这个就是分组的key,我们这里是对年龄分组。

       initial: 每组都分享一个”初始化函数“,特别注意:是每一组,比如这个的age=20的value的list分享一个

initial函数,age=22同样也分享一个initial函数。

       $reduce: 这个函数的第一个参数是当前的文档对象,第二个参数是上一次function操作的累计对象,第一次

为initial中的{”perosn“:[]}。有多少个文档, $reduce就会调用多少次。

技术分享

   看到上面的结果,是不是有点感觉,我们通过age查看到了相应的name人员,不过有时我们可能有如下的要求:

     ①:想过滤掉age>25一些人员。

     ②:有时person数组里面的人员太多,我想加上一个count属性标明一下。

 针对上面的需求,在group里面还是很好办到的,因为group有这么两个可选参数: condition 和 finalize。

     condition:  这个就是过滤条件。

     finalize:这是个函数,每一组文档执行完后,多会触发此方法,那么在每组集合里面加上count也就是它的活了。

技术分享

 

<4> mapReduce

        这玩意算是聚合函数中最复杂的了,不过复杂也好,越复杂就越灵活。

  mapReduce其实是一种编程模型,用在分布式计算中,其中有一个“map”函数,一个”reduce“函数。

   ① map:

          这个称为映射函数,里面会调用emit(key,value),集合会按照你指定的key进行映射分组。

   ② reduce:

         这个称为简化函数,会对map分组后的数据进行分组简化,注意:在reduce(key,value)中的key就是

      emit中的key,vlaue为emit分组后的emit(value)的集合,这里也就是很多{"count":1}的数组。

   ③ mapReduce:

          这个就是最后执行的函数了,参数为map,reduce和一些可选参数。具体看图可知:

技术分享

 

从图中我们可以看到如下信息:

       result: "存放的集合名“;

       input:传入文档的个数。

       emit:此函数被调用的次数。

       reduce:此函数被调用的次数。

       output:最后返回文档的个数。

最后我们看一下“collecton”集合里面按姓名分组的情况。

技术分享

 

二:游标

    mongodb里面的游标有点类似我们说的C#里面延迟执行,比如:

      var list=db.person.find();

    针对这样的操作,list其实并没有获取到person中的文档,而是申明一个“查询结构”,等我们需要的时候通过

for或者next()一次性加载过来,然后让游标逐行读取,当我们枚举完了之后,游标销毁,之后我们在通过list获取时,

发现没有数据返回了。

技术分享

 

当然我们的“查询构造”还可以搞的复杂点,比如分页,排序都可以加进去。

 var single=db.person.find().sort({"name",1}).skip(2).limit(2);

那么这样的“查询构造”可以在我们需要执行的时候执行,大大提高了不必要的花销。

技术分享

 
索引优化 

   我们首先插入10w数据,上图说话:

技术分享

 

一:性能分析函数(explain)

好了,数据已经插入成功,既然我们要做分析,肯定要有分析的工具,幸好mongodb中给我们提供了一个关键字叫做“explain",那么怎么用呢?

还是看图,注意,这里的name字段没有建立任何索引,这里我就查询一个“name10000”的姓名。

技术分享

 

 

二:建立索引(ensureIndex)

     在10w条这么简单的集合中查找一个文档要114毫秒有一点点让人不能接收,好,那么我们该如何优化呢?mongodb中给

我们带来了索引查找,看看能不能让我们的查询一飞冲天.....

     技术分享

  这里我们使用了ensureIndex在name上建立了索引。”1“:表示按照name进行升序,”-1“:表示按照name进行降序。

 

三:唯一索引

     和sqlserver一样都可以建立唯一索引,重复的键值自然就不能插入,在mongodb中的使用方法是:

db.person.ensureIndex({"name":1},{"unique":true})。

技术分享

 

四:组合索引

     有时候我们的查询不是单条件的,可能是多条件,比如查找出生在‘1989-3-2’名字叫‘jack’的同学,那么我们可以建立“姓名”和"生日“

的联合索引来加速查询。

技术分享

看到上图,大家或者也知道name跟birthday的不同,建立的索引也不同,升序和降序的顺序不同都会产生不同的索引,

那么我们可以用getindexes来查看下person集合中到底生成了那些索引。

技术分享

 

 

五: 删除索引

     可能随着业务需求的变化,原先建立的索引可能没有存在的必要了,可能有的人想说没必要就没必要呗,但是请记住,索引会降低CUD这三种操作的性能,因为这玩意需要实时维护,所以啥问题都要综合考虑一下,这里就把刚才建立的索引清空掉来演示一下:dropIndexes的使用。

技术分享

部署在windows服务 

 

 我之前的文章都是采用console程序来承载,不过在生产环境中这并不是最佳实践,谁也不愿意在机器重启后满地找牙似找mongodb,

在mongodb里面提供了一个叫做“服务寄宿”的模式,我想如果大家对wcf比较熟悉的话很容易听懂。好了,我们实践一下,这里我开一下D盘

里面的mongodb。

 

技术分享

这里要注意的有两点:

   <1> logpath: 当我们使用服务寄宿的时候,用眼睛都能想明白肯定不会用console来承载日志信息了。

   <2> install:   开启安装服务寄宿,很happy啊,把管理员的手工操作降低到最小,感谢mongodb。

 

好了,console程序叫我看log日志,那我就看看,发现mongodb已经提示我们如何开启mongodb,接着我照做就是了。

技术分享

 

还要提醒大家一点的就是,这些命令参数很多很复杂也就很容易忘,不过没关系,数据库给我们提供了一个help方法,我们可以

拿mongod和mongo说事。

mongod:

技术分享

 

mongo:

技术分享

 

操作链接---
bin目录下  mongo --port 2222 即可链接部署在windows服务的 mongodb,不需要cmd长时间运行
 

备份

   这玩意的重要性我想都不需要我来说了吧,这玩意要是搞不好会死人的,mongodb里面常用的手段有3种。

1: 直接copy

       这个算是最简单的了,不过要注意一点,在服务器运行的情况下直接copy是很有风险的,可能copy出来时,数据已经遭到

        破坏,唯一能保证的就是要暂时关闭下服务器,copy完后重开。

2:mongodump和mongorestore

      这个是mongo给我们提供的内置工具,很好用,能保证在不关闭服务器的情况下copy数据。

为了操作方便,我们先删除授权用户。

技术分享

 

好了,我们转入正题,这里我先在D盘建立一个backup文件夹用于存放test数据库。

技术分享

快看,数据已经备份过来了,太爽了,现在我们用mongorestore恢复过去,记住啊,它是不用关闭机器的。

技术分享

提一点的就是 drop选项,这里是说我将test数据恢复之前先删除原有数据库里面的数据,同样大家可以通过help查看。

 

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

 

Mongodb数据库的新建与删除(在cmd中的操作)
进入mongodb数据库后,可以先查看下当前存在的数据库:show dbs; 运行结果如图,我本地目前有2个数据库。
技术分享 
下面直接使用use命令,就可以直接创建一个数据库,如:use mydb; 这时候,数据库已经存在,只不过是空的。然后我们插入一条数据,如:db.user.insert({‘name‘ : ‘nosql‘}); 。这时候再查看数据库:show dbs; 就可以看到新的数据库了。
 
mongodb数据库的删除
进入mongodb数据库后,进入需要删除的数据库,比如刚刚新建的mydbs:use mydb; ,然后运行命令删除命令:db.dropDatabase(); ,这时候数据库已经删除。此时我们切换到默认数据库test下:use test; ,然后查看目前的数据库:show dbs; ,可以看到数据库已经被删除了。
 ----------

 

 

MongoDB基础