学习MongoDB--(3-1):创建、删除及更新文档

这次主要详细讲解一下通过Shell对文档进行的各种操作,前面我们知道运行mongo命令可以得到一个MongoDB的客户端,在这里可以对数据库发出命令进行各种操作。一般我们假定他和数据库服务运行在同一台机器上,还假定数据库服务使用默认的端口27017,但mongo本身命令还是很强大的,支持远程连接到另一台服务器,也支持连接不同端口,如下操作即可:

通过mongo命令连接机器192.168.100.100端口20000上的MongoDB服务,并且默认连接数据库admin。如果我们启动Shell仅是想实验一下JavaScript,则运行 mongo --nodb 得到的Shell没有连接任何数据库。

我们都知道在Shell中提供一个全局变量db指向当前连接的数据库。但我们还可以有很多变量去连接不通的数据库,利用Shell中提供的connect()命令即可:

让变量studb指向数据库students。db依然指向默认的数据库test。

【插入并保存文档】

这个前面已经有所提及,就是利用集合的insert方法即可,接受的参数就是一个文档。对于文档插入,MongoDB支持并推荐更高效批量插入,一次批量插入只会发送一个TCP请求,一个头部信息,所以比单条插入要快很多。但MongoDB的Shell没有提供批量插入的支持,这个等到具体语言访问MongoDB时再做演示了。

【删除文档】

利用集合的remove方法即可,如果该方法不接受任何参数,则代表清空整个集合,该方法也可以接受一个查询文档作为可选参数,如db.students.remove({"age":18}); 删除集合students中所有年龄为18岁的学生的文档信息。remove方法会删除文档,但不会影响到集合本身,集合上建立的索引也会保留。如果要删除整个集合内容,我们还可以考虑直接删除集合,这样会更高效并且将所有索引也会一起删除。

对于删除整个集合,《MongoDB权威指南》中提到的db.drop_collection("集合名")在Shell中无法执行,调用db.help()查看数据库可以调用的方法中也没有这个方法。但数据库提供了这个方法: db.dropDatabase() ,不接受任何参数,会将数据库中所有的集合全部删除。调用  db.集合名.help() 查看Shell中为集合提供的所有函数,发现其有一个drop函数,用于删除当前的集合。

【更新文档】

文档存入到数据库后,就可以通过集合的update方法对文档进行更新。update接受两个参数,第一个是查询文档,即通过这个参数定位要更新数据库中哪些文档,第二个是修改器文档,即代表对找到的文档进行哪些更新操作。更新操作最简单的形式是:完全用一个新文档替换待修改的文档(即数据库中匹配查询文档的文档)。这里的替换是指全部键值对的替换,如果你提供的新的文档中包含“_id”键值对,则该方法会将这个新文档全部覆盖原始待替换文档,如果没有"_id"键,则更新操作仅仅会保留原始文档中的"_id"键值对。

> use mylearndb;
switched to db mylearndb
> show collections;
blogs
system.indexes
> db.blogs.insert({"title":"my second blog", "contents":"how to learn java"});
> db.blogs.find();
{ "_id" : ObjectId("501df90605f64f64b0765c51"), "title" : "my first blog", "cont
ents" : "how to learn english" }
{ "_id" : ObjectId("501df9ba05f64f64b0765c52"), "title" : "my second blog", "con
tents" : "how to learn java" }
> db.blogs.update({"title":"my first blog"},
... {"comments":"good"});
> db.blogs.find();
{ "_id" : ObjectId("501df90605f64f64b0765c51"), "comments" : "good" }
{ "_id" : ObjectId("501df9ba05f64f64b0765c52"), "title" : "my second blog", "con
tents" : "how to learn java" }
>

对于上述更新操作,其完全替换的方式其实是违背了我们的本意,我们原本就是想为文档添加"comments"键,结果将原始文档完全替换掉了,我们需要这样使用update:

> db.blogs.find();
{ "_id" : ObjectId("501df9ba05f64f64b0765c52"), "title" : "my second blog", "con
tents" : "how to learn java" }
> var secondblog = db.blogs.findOne({"title":"my second blog"});
> secondblog.comments = "good";
good
> db.blogs.update({"title":"my second blog"}, secondblog);
> db.blogs.find();
{ "_id" : ObjectId("501df9ba05f64f64b0765c52"), "title" : "my second blog", "con
tents" : "how to learn java", "comments" : "good" }
>

如上这种更新方式,我们需要注意一个问题,就是变量secondblog 必须通过findOne()去获得,如果通过find()方法获得,则后面的update方法会报错:

> secondblog = db.blogs.find({"title":"my second blog"});
{ "_id" : ObjectId("501df9ba05f64f64b0765c52"), "title" : "my second blog", "con
tents" : "how to learn java", "comments" : "good" }
> secondblog.comments = "just so so";
just so so
> db.blogs.update({"title":"my second blog"}, secondblog);
Sun Aug 05 13:01:03 uncaught exception: can't save a DBQuery object
>

使用这种全部替换文档的更新方式,还需注意一点的是,因为findOne方法仅会返回查询文档匹配的一条集合文档,我们对其操作后,在update时,此处update按照查询文档可能不止返回一条集合文档,那么全部替换就会失败,因为会出现集合中"_id"键值重复的现象,如:

> db.people.find();
{ "_id" : ObjectId("501dffc605f64f64b0765c53"), "name" : "drifter", "age" : 18 }

{ "_id" : ObjectId("501dffcc05f64f64b0765c54"), "name" : "drifter", "age" : 28 }

{ "_id" : ObjectId("501dffd005f64f64b0765c55"), "name" : "drifter", "age" : 38 }

> var drifter28 = db.people.findOne({"name":"drifter", "age":28});
> drifter28.age++;
28
> db.people.update({"name":"drifter"}, drifter28);
cannot change _id of a document old:{ _id: ObjectId('501dffc605f64f64b0765c53'),
 name: "drifter", age: 18.0 } new:{ _id: ObjectId('501dffcc05f64f64b0765c54'), n
ame: "drifter", age: 29.0 }
>

所以最好在替换式更新,最好能确保指定唯一文档进行替换,例如通过"_id"键去定位这条待替换文档。

最后再说一下,MongoDB会保证更新操作是原子性的,如果两个客户端对同一条文档进行更新,请求先到达的先执行,然后另一个更新请求再执行。后一条更新操作会覆盖前一条的更新操作!

在实验时,发现Shell中命令区分大小写!这个作为本次学习的结束语吧。


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值