MongoDB创建更新和删除文档

MongoDB最基础的部分已经看的差不多了,作为数据库来说做的最多的还是对数据库数据的操作。本文将介绍MongoDB中一下三点

      • 向集合中添加新文档
      • 从集合中删除文档
      • 更新现有文档

插入并保存文档

插入一条记录

> db.user.find()
{ "_id" : ObjectId("51b28f74b73ec06e42c91598"), "username" : "wangwu", "password
" : "121212", "tel" : "121212" }
> db.user.insert({username:'aaa',password:'bbb',tel:'123123123'});
> db.user.find()
{ "_id" : ObjectId("51b28f74b73ec06e42c91598"), "username" : "wangwu", "password
" : "121212", "tel" : "121212" }
{ "_id" : ObjectId("51b91edc32b7955cd61dbc8e"), "username" : "aaa", "password" :
 "bbb", "tel" : "123123123" }
>


操作为文档增加了一个“_id”,然后保存到了MongoDB中

> db.user.insert({_id:'12345678',username:'aaa',password:'bbb',tel:'123123123'})
;
> db.user.find();
{ "_id" : ObjectId("51b28f74b73ec06e42c91598"), "username" : "wangwu", "password
" : "121212", "tel" : "121212" }
{ "_id" : ObjectId("51b91edc32b7955cd61dbc8e"), "username" : "aaa", "password" :
 "bbb", "tel" : "123123123" }
{ "_id" : "12345678", "username" : "aaa", "password" : "bbb", "tel" : "123123123
" }
>

如果我们自己定义了一个_id的话,数据库就不在自己生存,可以看到数据库自己生成的是ObjectId。

批量插入

如果要插入多个文档,批量要快一些。批量插入能传递一个由文档构成的数组给数据库

一次发送多个文档会提高插入数度。一次插入需要建立一个TCP链接。批量提交,会比多次提交数据少建立TCP连接,避免了零碎的请求开销。而且批量提交只会有一个文件头信息,数据不用多次的处理文件头。

用数组的方式一次插入两条数据

> db.user.insert([{username:'aaa',password:'bbb',tel:'123123123'},{username:'bbb
',password:'ccc',tel:'123123234'}]);
> db.user.find()
{ "_id" : ObjectId("51b28f74b73ec06e42c91598"), "username" : "wangwu", "password
" : "121212", "tel" : "121212" }
{ "_id" : ObjectId("51b91edc32b7955cd61dbc8e"), "username" : "aaa", "password" :
 "bbb", "tel" : "123123123" }
{ "_id" : "12345678", "username" : "aaa", "password" : "bbb", "tel" : "123123123
" }
{ "_id" : ObjectId("51b920ca32b7955cd61dbc8f"), "username" : "aaa", "password" :
 "bbb", "tel" : "123123123" }
{ "_id" : ObjectId("51b920ca32b7955cd61dbc90"), "username" : "bbb", "password" :
 "ccc", "tel" : "123123234" }
>

插入原理和作用

当执行插入事,使用的驱动会将数据转换为BSON的形式,将其送入数据库。数据库解析BSON,检验是否有_id,和文档的大小,除此之外,文档不做别的数据验证,简单的将数据存入数据库中。

ps.大于4M的文档是不能存入数据库中的。

删除文档

删除文档用

> db.user.remove()

如果remove不传入任何参数,会删除所有文档,但不会删除集合本身,原索引也会保留。

如果给定参数,只有符合条件的才会删除

> db.user.remove({username:'aaa'})
> db.user.find();
{ "_id" : ObjectId("51b28f74b73ec06e42c91598"), "username" : "wangwu", "password
" : "121212", "tel" : "121212" }
{ "_id" : ObjectId("51b920ca32b7955cd61dbc90"), "username" : "bbb", "password" :
 "ccc", "tel" : "123123234" }
>


删除速度

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

更新文档

文档存入数据库后,就可以用update方法来修改它,update有两个参数一个是查询文档,找出需要更新的文档。一个是修改文档,描述对找到的文档做哪些修改

更新操作是原子的,若是两个更新同时发生,先到达服务器的先执行。

文档替换

更新最简单的就是完全用一个新文档替代匹配文档。比如我们将username为bb的文档替换为如下

> db.user.update({username:'bbb'},{password:'abc'});
> db.user.find();
{ "_id" : ObjectId("51b28f74b73ec06e42c91598"), "username" : "wangwu", "password
" : "121212", "tel" : "121212" }
{ "_id" : ObjectId("51b920ca32b7955cd61dbc90"), "password" : "abc" }
>

我们发现文档结构被替换成了

{ "_id" : ObjectId("51b920ca32b7955cd61dbc90"), "password" : "abc" }
>

也就是说这样的替换是直接替换文档,而不是做修改。在大的改动的情况下,使用文档变更可以直接替换文档,但有时候这样却不是我们想要的,我们只是希望修改password而不变动其他的内容

使用修改器

通常文档只会有部分要更新。利用原子的修改器,可以用来部分更新。

$set修改器

$set用来指定一个键的值,如果这个键不存在,就创建它。下面我们修改username为wangwu的password的值

> db.user.find();
{ "_id" : ObjectId("51b28f74b73ec06e42c91598"), "username" : "wangwu", "password
" : "121212", "tel" : "121212" }
{ "_id" : ObjectId("51b920ca32b7955cd61dbc90"), "password" : "abc" }
> db.user.update({username:'wangwu'},{$set:{password:'abcdef'}});
> db.user.find();
{ "_id" : ObjectId("51b28f74b73ec06e42c91598"), "username" : "wangwu", "password
" : "abcdef", "tel" : "121212" }
{ "_id" : ObjectId("51b920ca32b7955cd61dbc90"), "password" : "abc" }
>

$unset修改器

$unset来删除一个键,比如删除username为wangwu的tel键

> db.user.update({username:'wangwu'},{$unset:{tel:1}});
> db.user.find();
{ "_id" : ObjectId("51b28f74b73ec06e42c91598"), "password" : "abcdef", "username
" : "wangwu" }
{ "_id" : ObjectId("51b920ca32b7955cd61dbc90"), "password" : "abc" }
>

$inc修改器

$inc用来增加已有的键值,或者在键值不存在时创建。

现在我们需要一个age的值

现在给age执行$inc

> db.user.find()
{ "_id" : ObjectId("51b28f74b73ec06e42c91598"), "password" : "abcdef", "username
" : "wangwu" }
{ "_id" : ObjectId("51b920ca32b7955cd61dbc90"), "password" : "abc" }
> db.user.update({username:'wangwu'},{$inc:{age:1}});
> db.user.find()
{ "_id" : ObjectId("51b28f74b73ec06e42c91598"), "age" : 1, "password" : "abcdef"
, "username" : "wangwu" }
{ "_id" : ObjectId("51b920ca32b7955cd61dbc90"), "password" : "abc" }
> db.user.update({username:'wangwu'},{$inc:{age:1}});
> db.user.find()
{ "_id" : ObjectId("51b28f74b73ec06e42c91598"), "age" : 2, "password" : "abcdef"
, "username" : "wangwu" }
{ "_id" : ObjectId("51b920ca32b7955cd61dbc90"), "password" : "abc" }
>


这里执行了两次$inc,age第一次创建了一个值为1的键值,然后自加了1.

$inc键的值必须为数字,如果尝试修改成其他类型就会出现如下错误

> db.user.update({username:'wangwu'},{$inc:{age:'abc'}});
Modifier $inc allowed for numbers only
>


数组修改器

数组修改器只能用于数组。

$push会像已有的数组末尾假如一个元素

$pop会从头部删除一个元素

> db.user.find()
{ "_id" : ObjectId("51b28f74b73ec06e42c91598"), "age" : 2, "password" : "abcdef"
, "username" : "wangwu" }
{ "_id" : ObjectId("51b920ca32b7955cd61dbc90"), "password" : "abc" }
> db.user.update({username:'wangwu'},{$push:{arr:1}});
> db.user.find()
{ "_id" : ObjectId("51b920ca32b7955cd61dbc90"), "password" : "abc" }
{ "_id" : ObjectId("51b28f74b73ec06e42c91598"), "age" : 2, "arr" : [  1 ], "pass
word" : "abcdef", "username" : "wangwu" }
> db.user.update({username:'wangwu'},{$push:{arr:2}});
> db.user.find()
{ "_id" : ObjectId("51b920ca32b7955cd61dbc90"), "password" : "abc" }
{ "_id" : ObjectId("51b28f74b73ec06e42c91598"), "age" : 2, "arr" : [  1,  2 ], "
password" : "abcdef", "username" : "wangwu" }
> db.user.update({username:'wangwu'},{$pop:{arr:2}});
> db.user.find()
{ "_id" : ObjectId("51b920ca32b7955cd61dbc90"), "password" : "abc" }
{ "_id" : ObjectId("51b28f74b73ec06e42c91598"), "age" : 2, "arr" : [  1 ], "pass
word" : "abcdef", "username" : "wangwu" }
> db.user.update({username:'wangwu'},{$pop:{arr:2}});
> db.user.find()
{ "_id" : ObjectId("51b920ca32b7955cd61dbc90"), "password" : "abc" }
{ "_id" : ObjectId("51b28f74b73ec06e42c91598"), "age" : 2, "arr" : [ ], "passwor
d" : "abcdef", "username" : "wangwu" }


数组的定位修改器

若是数组中多个值,我们只想修改其中的部分值,有两种方法操作数组中的值:通过位置和定位操作符($)

> db.user.update({username:'wangwu'},{$set:{'arr.1':1}});
> db.user.find()
{ "_id" : ObjectId("51b920ca32b7955cd61dbc90"), "password" : "abc" }
{ "_id" : ObjectId("51b28f74b73ec06e42c91598"), "age" : 2, "arr" : [  2,  1,  3,
  4 ], "password" : "a", "username" : "wangwu" }
> db.user.update({username:'wangwu'},{$set:{'arr.$':1}});
Cannot apply the positional operator without a corresponding query field contain
ing an array.
> db.user.update({'arr.1':1},{$set:{'arr.$':1}});
> db.user.update({'arr.1':1},{$set:{'arr.$':3}});
> db.user.find()
{ "_id" : ObjectId("51b920ca32b7955cd61dbc90"), "password" : "abc" }
{ "_id" : ObjectId("51b28f74b73ec06e42c91598"), "age" : 2, "arr" : [  2,  3,  3,
  4 ], "password" : "a", "username" : "wangwu" }
>

使用位置可以直接修改指定位置的数据,使用定位操作符是在查询的时候不知道该位置的时候使用,这个时候需要注意的是查询username的时候,使用$会报出错误。也就是查询出来的值不是数组,所以不能用$来指定

 

upsert

upsert是一个特殊的更新。当没有文档符合更新条件,就会以这个条件创建新的文档。当update的第三个参数设置为true的时候,为upsert模式

> db.user.find()
{ "_id" : ObjectId("51b28f74b73ec06e42c91598"), "age" : 2, "arr" : [  2,  3,  3,
  4 ], "password" : "a", "username" : "wangwu" }
> db.user.update({age:1},{$set:{abc:123}},true)
> db.user.find()
{ "_id" : ObjectId("51b28f74b73ec06e42c91598"), "age" : 2, "arr" : [  2,  3,  3,
  4 ], "password" : "a", "username" : "wangwu" }
{ "_id" : ObjectId("51ba745f5fdf5d2d7426eb35"), "abc" : 123, "age" : 1 }
>

 

更新多个文档

默认情况下,更新只能对符合匹配条件的第一个文档操作,要是有多个文档符合条件,其余的文档就没有变化。要使所有的文档都得到更新,可以设置update的第四个参数为true

返回已经更新的文档

用getLastError只能获取有限的信息,并不能返回更新的文档。这个可以通过findAndModify来做到。

安全操作

MongoDB选中选择不安全的版本作为默认操作,如果需要判断状态,在执行完操作后立即运行getLastError,来检查是否成功。

如果不考虑安全性的问题,就无序调用getLastError

把重要的数据用安全的方式操作

请求和连接

数据库为MongoDB创建了一个队列,存放这个连接请求。当客户端发送一个请求,会被放到队列的末尾。只有队列中的请求都执行完毕,后续的请求才会执行。每个连接都有独立的队列。

posted @ 2013-06-13 12:54  张巍的博客  阅读(3140)  评论(0编辑  收藏  举报