MongoDB学习笔记—03 增删改查操作

MongoDB的CURD操作分别通过函数insert()、update()、find()、remove()进行

MongoDB文档新增与删除

MongoDB中关于文档的新增与删除比较简单。主要通过insert方法数和remove方法进行。

文档新增

对目标集使用insert方法,可以插入一个文档,如:

db.user.insert({"name":"wangxs"})

若新增的文档没有"_id"键,则会自动添加。db.user.insert({"_id":"1,"name":"wangxs"})

批量插入:传递一个由文档构成的数组(数组由中括号表示[])给insert方法。如:

db.user.insert([{"name":"wangxs"},{"name":"wdh"},{"name":"cxx"}])

批量插入能够减少插入时间,因为一次插入就是一次TCP请求,而批量插入无需处理大量的消息头。

插入的原理

执行插入时,驱动程序会将数据转换成BSON的形式,然后将其送入数据库,数据库接下BSON,检验是否包含"_id"键并且文档不超过4MB,除此之外不做别的数据验证,只是简单的将文档原样存入数据库中。坏处是允许插入无效的数据,好处是可以远离注入式攻击(插入时并不执行代码),使数据库更安全。

可以在启动数据库服务器时使用--objcheck选项,这样服务器就会在插入之前检查文档的有效性(牺牲了速度)。

BSON

BSON:Binary JSON;是轻量的二进制格式,能够将MongoDB的所有文档表示成字节字符串,存在磁盘也是这种格式。同样,返回到客户端的文档也是BSON格式的字符串。驱动会进行解析并呈现。

BSON格式有下面3个主要的优点:更有效的表示数据,减少占用空间;牺牲空间效率,换取更容易的遍历格式;BSON的编码和解码的速度快,提高性能。

删除文档

使用remove方法对目标集进行数据的清除。如:

db.user.remove()

这种方式只会删除user集合的所有文档,而不删除集合本身,原有的索引也会被保留。

指定删除条件:remove函数接收一个文档作为条件参数,只有符合此条件的文档才会被删除,如:db.user.remove({{"age":22}});该命令删除user集合中年龄为22岁的文档。

数据的删除是永久性的,不能撤销也不能恢复。

删除速度:删除文档通常很快,但要清除整个集合,直接删除集合会更快

查找文档

文档查找涉及到一下几个方面:1)使用find或findOne函数和给定条件进行查询;2)使用$条件查询实现范围、集合包含、不等式和其他查询;3)$where子句或javascript进行复杂查询;4)对查询结果进行分页、排序等。

find函数

MongoDB使用find函数来进行查询,第一个参数决定了要返回哪些文档。若不指定查询文档,默认是{},表示匹配集合的全部内容。

例如:>db.user.find() // 将返回user集合的全部内容

向查询文档添加键值对时,意味着限定查找的条件。例如:

>db.user.find({"age":22}) // 查找user集合中年龄为22岁的用户

> db.user.find({"name":"wangdh"}) // 查找user集合中名字为wangdh的用户

向查询文档中添加多个键值对时,表示多条件组合查询(And操作),例如:

>db.user.find({"name":"wangdh","age":22}) //查找user集合中名字为wangdh且年龄为22岁的用户

指定返回的键(节省传输的数据量、解码文档的时间和内存占用)

有时并不需要将文档中的所有键值对都返回,可以通过find函数的第二个参数指定想要返回的键;例如:

>db.user.find({},{"name":1, "age":1}) // 返回_id、name、age三个键(默认返回_id键)。

>db.user.find({},{"_id":0}) // 返回除_id键外的所有键

查询条件

除了精确查询之外,还可以进行范围、OR、取反等复杂的查询。

1)数字和日期

数字和日期经常会有比较大小的操作,即<、<=、>、>=等操作,在MongoDB中,分别对应于:$lt、$lte、$gt、$gte等比较操作符。例如:

>db.user.find({"age":{"$gte":18,"$lte":30}}) //查询年龄在18-30(含)的用户

>start = new Date("01/01/2003")

>db.user.find({"birthday":{"$lt":start}}) // 查询在2003-01-01之前出生的用户

>db.user.find({"age":{"$ne":22}}) // 查询年龄不为22岁的用户、$ne操作符可用于任何数据类型

2)OR查询

MongoDB有两种方式来进行OR查询。$in操作符可以匹配一个键的多个值;$or操作符可以匹配多个键的任意给定值。相比之下$or操作符更通用。

>db.user.find({"age":{"$in":[22,25,30]}}) // 查询年龄为22、25、30的用户

> db.user.find({"age":{"$nin":[22,25,30]}}) // 查询年龄不为22、25、30的用户

>db.user.find({"$or":{"name":"wangdh"},{"age":22}}) // 查找姓名为wangdh或者年龄为22岁的用户

>db.user.find({"$or":{"name":"wangdh"},{"age":{""$in:[22,25,30]}}}) // 查找姓名为wangdh或者年龄为22、25、30岁的用户

3)$not、$mod操作符

$not是元条件句,可以用在其他条件之上,$mod是取模运算

>db.user.find({"num":{"$mod":[5,1]}}) // 返回num键的值除以5余1的文档

>db.user.find({"num":{"$or":{"$mod":[5,1]}}}) // 返回num键的值除以5不余1的文档

特定类型的查询

针对有特别表示的数据进行的查询,如:null

1)null

null不仅匹配自身,即值为null,也匹配不存在(缺少这个键);例如:

>db.user.find({"y":null})

>db.user.find({"y":{"$in":[null], "$exists":true}}) // 仅匹配null值,通过$exists键值为true来判定键已存在

2)正则表达式

正则表达式能够灵活有效的匹配字符串。MongoDB中的正则表达式与javascript的类似。

>db.user.find({"name":/joe/i}) // 匹配姓名为Joe的用户,忽略大小写

3)查询数组

数组可以理解为每个元素都是对应键的值,如:

>db.food.insert({"fruit":["apple","banana","peach"]})

>db.food.find({"fruit":"apple"}) // 该查询会匹配上述插入的文档

4)查询内嵌文档

查询整个文档或只针对其减值对进行查询。使用点表示法查询内嵌的键:

>db.user.find({"name.first":"wang","name.last":"donghong"})

$where查询

比较文档中两个键的值是否相等:

>db.food.find({"$where":function(){

for(var current in this){

    for(var other in this){

       if(current!=other && this[current]==this[other]){

           return true;

         }

     }

}

return false;

}})

>db.find.find({"$where":"this.x+this.y==10"})

等价于

> db.find.find({"$where":"function(){return this.x+this.y==10;}"})

分页与排序

采用limit、skip和sort来实现限制返回结果的数量、忽略一定数量的结果并排序。

>db.food.find().limit(3) // 限制返回3个文档

>db.food.find().skip(3) // 跳过前3个文档,返回余下的文档。

sort用一个对象作为参数:一组键值对,键对应文档的键名,值代表排序的方向(1表示升序,-1表示降序)。如果指定多个键,则按照键的顺序逐个排序:

>db.user.find().sort({"name":1,"age":-1}) // 按照name升序,age降序

避免使用skip忽略大量结果,因为会变得很慢。

一种分页的思想:先按照某个键进行排序并使用limit限制返回的个数,下一次使用上一次的排序键的最大值作为筛选条件且使用limit,如此反复下去…

更新文档

使用update函数来修改存在数据库中的文档。update有俩个参数:第一个是查询文档,用来找出需要更新的文档,第二个是修改器文档,描述对找到的文档做和修改。

文档替换

使用新的文档来替代匹配到的文档,如:

>db.user.update({"name":"wangdh"},{"age":21,"sex":"男"})

当查询条件匹配到多个文档且第二个参数存在_id键时,会因为插入重复的_id值导致数据库报错。

局部更新:使用修改器

$set修改器:用来指定一个键的值,如果这个键不存在,则创建它,存在则用新指定的值替换该键原来的值,如:

>db.user.update({"name":"wangdh"},{"$set":{"lover":"cxx"}})

$unset修改器可以将指定的键删除掉:

>db.user.update({"name":"wangdh"},{"$unset":{"lover":1}})

$inc修改器:增加已有键的值,不存在时创建

>db.user.update({"name":"wangdh"},{"$inc":{"age":1}}) // 将年龄加1

$inc修改器修改的键的值必须是数字,否则会报错。

数组修改器

只能用在值为数组的键上。

$push修改器:向已有数组的末尾加入一个元素。

>db.blog.post.update({"title":"test"},{"$push":{"comments":{"content":"test content"} }})

$pop修改器:从数组任何一端删除元素,{"$pop":{"key":1}}尾部删除{"$pop":{"key":1}}头部删除。

upset更新:没有记录则插入

通过指定update的第三个参数为true来实现。当有匹配文档时,则进行更新,否则进行插入。

批量更新

通过指定update的第四个参数为true来执行批量更新。当匹配到多个文档且第四个参数为true时,对所有匹配到的文档进行更新操作。

posted @ 2014-12-18 21:58  王小帅  阅读(378)  评论(0编辑  收藏  举报