MongoDB 学习笔记(二):shell中执行增删查改

一、查

1、查询集合中所有文档:db.集合名.find()

2、查询集合中第一个文档:db.集合名.findOne()

3、指定查询条件:第一个参数就是指定查询条件

  • 查询全部文档:db.集合名.find({}),如下图:

       

  • 五种基本的查询条件:$lt(<)、$lte(<=)、$gt(>)、$gte(>=)、$ne(!=),如下图:从第 一个实验可以发现,当对某个key,该key的value中同时指定了多个查询条件,这些查询条件的关系是“与”关系;但是从第二个和第三个实现中可以发 现,当对某个key,分开指定了多次查询条件,则对该key的查询条件是以最后一个查询条件为准。

       

  • 包含与不包含:$in、$nin,都只能作用于数组,而不能作用于其他类型,如下图:

       

  • or查询:$or,如下图:注意最外面是or查询器,or查询器的value是一个数组,里面是很多的查询条件,数组中每个查询条件就是or的关系。

       

  • null查询:如下图

       

  • 正则查询:查询name这个key对应的value中包含有字母a的文档,如下图:

       

  • $not:可以用到任何地方进行取反的操作,与$nin的区别就在于$nin只能用在数组上,如下图:

        

  • 数组查询$all与index的应用:

        查询出books这个key对应的value中(对应类型是数组)同时存在“JS”与“JSP”这两个元素的文档,如下图:

       

        查询出books这个key对应的value中(对应类型是数组)第2个元素是“JS”的文档,如下图:注意,使用到了“.”的形式,需要加上引号

       

  • $size:查询指定长度的数组,它不能与比较查询符一起使用。查询出books这个key对应的value中(对应类型是数组)元素个数为1的文档,如下图:

       

  • 查询出某个文档中某个key(假设类型是数组)的元素个数,如下图:使用find查询出来的结果由于结果集的数量不定,所以查询出来的不的一个对象,是一个游标,所以需要用到游标遍历的方式来遍历查询出来的每个对象,而findOne就可以直接输出。

       

  • 数组查询:集合中的文档有一个key,是数组类型,数组中每个元素又是一个对象,如下图:

       

        如上图所示,查询条件是数组元素,这里没有使用任何额外的查询符,当查询条件与数组中元素(对象)完全匹配且顺序一致时才能查询出来。为了解决这个问题,可以使用“.”的方式,如下图:

       

        这样就解决了顺序问题和完全匹配的问题,但是这里会有个问题存在,如下图:

       

        其中courses.score:95满足文档中courses这个key的value中的第二个元素,而courses.course:Math满足文 档中courses这个key的value中的第一个元素,因为这里的每个查询条件都会被MongoDB进行遍历查询,只要其中有个元素满足了第一个查询 条件,再接着按第二个查询条件查询,然后再有任一个元素满足就算查询成功。所以为了解决这样的问题,可以使用条件组合查询符$elemMatch,它能同时解决以上存在的全部问题,如下图:把条件当成一个组合进行查询,

        只有当一个文档的满足这个组合条件才算查询成功。

       

  • $where查询:在一些比较复杂的查询中使用$where查询很方便,但是$where查询存在一个性能问题,应该少用,如下图:查询年龄为22岁,有JS这本书且选修了Math这门课程的文档。

       

4、查询指定key:第二个参数就是指定要查询的key,如下图:想要查询出哪个key,就将其对应的value置为1,默认情况下会将_id也查询出来,可以将其对应的value置为0,就不会查询出来了。

如上图中最后一个列子,既指定了要查询的name这个key,又指定了不查询的_id这个key,这里包含了要查询的key和要排除的key,但是在其他情况下不能混合使用,要么指定要查询的key,要么指定要排除的key,如下图:

如果对同一个key指定了两次,则以最后一次为准,如下图:

如果一个key是数组类型,还可以用$slice操作符指定显示的数组元素,如下图:前面几个都是指定从哪个数组元素索引开始,取多少个元素,而最后一个是只选取最后一个元素。

 

二、增

1、添加集合并插入一个文档:db.集合名.insert({...})

如下图:如果person集合不存在,则会为当前数据库添加一个名为“person”的集合,然后为该集合插入一个文档。

注意:MongoDB会自动为该文档加入一个“_id”的key,但是如果要插入的文档中已经包含了"_id"的key,则不会再自动添加了,如下:

以上执行insert时候传入的是一个对象,那么传入的是一个对象数组呢?如下图:如果插入时传入的是一个对象数组,那么会为该对象数组中的每一个对象插入一个文档。

2、批量插入

要完成批量插入可以用MongoDB的应用驱动或者是Shell中的for循环,如下图:

3、save与insert操作

当执行insert操作时,如果待插入的文档的“_id”这个key的值已经存在了(字面值一样且类型一样),则会报错,如下图

但是如果采用save方法遇到已经存在的"_id",则不会报错,它其实是把已经存在的“_id”的那个文档进行更新;当然,如果要插入的文档的"_id"值还不存在则插入新文档就是,如下图

三、删

1、删除集合中所有文档:db.集合名.remove(),集合本身和索引不会被删除。

2、根据条件删除:db.集合名.remove({...}),如下图:name为“eee”的全部被删除了。

四、改

1、强硬的文档替换式更新

此种更新操作类似于把之前的老文档删除,然后替换为更新的文档,也就是用新文档替换老文档,如下图:原文档中根本不存在age这个key,但是执行替换式更新后,不管老文档存在哪些key,更新最后都仅仅只会存在新的文档中的那些key。

不可以更新“_id”这个key的值,而不管更新后的“_id”值是否已经存在,如下图:

当满足更新条件的文档不止一个时,MongoDB只会更新第一个文档,如下图:

当没有任何文档满足更新条件时,以上这些更新都不会进行任何的更新;只有当满足更新条件时才会进行更新,如果没有满足更新条件的文档,要进行插入操作呢?那么可以使用update方法的第三个参数,如下:

2、使用修改器进行局部更新

2.1、$set修改器:{$set:{key:value}},如果满足更新条件的文档中存在$set修改器中的key时,则进行更新,否则进行添加,如下图:还是只会对满足条件的第一个文档进行更新

2.2、$inc修改器:{$inc:{key:value}},仅适用于数字类型,可以为指定的key对应的数字类型的值进行加减操作,如下图:

2.3、$unset修改器:{$unset:{key:value}},删除指定的key,如下图:

2.4、$push修改器:{$push:{key:value}},如果指定的key是数组,则往该数组中追加新的元素;如果指定的key不是数组,则中断操作;如果不存在指定的key,则创建,且类型为数组类型,并加入新的元素;如下图:

2.5、$pushAll修改器:{$pushAll:{key:value}},与$push一样,只是它可以一次性批量加入一个数组中的所有元素,如下图:

2.6、$addToSet修改器:{$addToSet:{key:value}},与$push一样,只是当目标数组不存在该元素时才加入,如下图:

2.7、$pop修改器:{$pop:{key:value}},从指定数组的头或尾删除一个元素,从头删除一个元素用小于-1的值,从尾删除一个元素用大于1的值,如下图:

2.8、$pull修改器:{$pull:{key:value}},从指定数组中删除一个被指定的值,如下图:

2.9、$pullAll修改器:{$pullAll:{key:value}},从指定数组中一次性删除多个被指定的值,如下图:

2.10、数组定位器$:如果数组中有多个元素,需要对其中一部分进行更新,则可以使用定位器$。如下图:可以发现它还是只会对该文档中books那个数组中满足条件的第一个元素其作用,且注意:当使用了books.price这种方式时,一定要加上引号,不然会报错。

2.11、$addToSet与$each结合完成批量数组更新,如下图:$each会循环后面的数组,把每个元素值进行$addToSet操作。

2.12、$push与$inc结合使用:比如要往文档的books这个key(数组)中加入一个元素,同时该文档的books_size这个key的大小加1,如下图:

3、批量更新

通过上面的实验可以发现以上的更新全部都只是会对满足更新条件的第一个文档进行更新,如果要对满足条件的所有文档进行批量更新则可以使用update的第四个参数,且这个参数要配合到修改器一起才会生效,强硬式替换更新无法进行批量操作,如下图:

 

4、其他用法

该可以先将满足条件的文档查询出来,并赋值给一个变量,然后再进行更新,如下:

5、文档内存分配与更新效率

当一个文档被创建的时候,MongoDB为其分配内存和预留内存,当更新操作不超过预留内存时速度非常快,但是当超过了预留内存后就要分配新的内存,所以会消耗时间,速度慢些。如下图:

五、其它函数

1、runCommand函数:可以执行MongoDB中的一些特殊函数。

2、findAndModify函数:它就是MongoDB中的一个特殊函数,用于返回更新前或后的文档,或者是删除的文档。它执行起来有些慢,因为它要等待数据库的响应,大概耗时相当于一次查找,一次更新和一次getLastError顺序执行所需的时间。但是对于操作查询以及执行其它需要取值和赋值风格的原子性操作来说是很方便的。该函数中每个键对应的值如下:

  • findAndModify:一个集合名,必须用引号括起来。
  • query:查询文档,用作检索文档的条件。
  • sort:排序结果的条件。
  • update:修改器文档,对所找到的文档执行更新。
  • remove:布尔类型,表示是否删除文档。
  • new:布尔类型,表示返回的是更新前的文档还是更新后的文档,默认是更新前的文档。
  • 说明:update和remove中必须有且仅有一个。要是匹配不到文档,该函数会返回一个错误。
  • 限制:该函数一次只能处理一个文档,所以只能更新或删除满足条件的第一个文档。也不能执行upsert操作,只能更新已有文档。

如下图:

 

 

posted @ 2013-10-18 10:30  chasewade  阅读(487)  评论(0编辑  收藏  举报