您的位置:首页 > 数据库 > Mongodb

MongoDB权威指南-增删查改

2015-09-10 18:08 471 查看
插入并保存文档

批量插入

db.foo.insert({"bar":"baz"})

这个操作会给文档自动增加一个"_id"键(要是原来没有的话)

db.foo.batchInsert([{"_id":0},{"_id":1},{"_id":2}])
当前版本的MongoDB能接受的最大消息长度是48MB,如果试图插入48MB以上的数据,多数驱动程序会将这个批量插入请求拆分为多个48MB的批量插入请求。
如果在执行批量插入的过程中有一个文档插入失败,那么在这个文档之前的所有文档都会成功插入到集合中,而这个文档以及之后的所有文档全部插入失败。
如果希望batchInsert忽略错误并且继续执行后续插入,可以使用continueOnError选项。

插入校验

插入数据时,MongoDB只对数据进行最基本的检查:检查文档的基本结构,如果没有"_id"字段,就自动增加一个。检查大小:所有文档都必须小于16MB
由于MongoDB只进行最基本的检查,应该只允许信任的源(比如你的应用程序服务器)连接数据库。

删除文档

删除速度

db.foo.remove()
上述命令会删除foo集合中的所有文档。但是不会删除集合本身,也不会删除集合的元信息。
db.mailing.remove({"opt-out":true})
删除操作是永久性的,不能撤销,也不能恢复。
如果要清空整个集合,那么使用drop直接删除集合会更快(然后在这个空集合上重建各项索引)

var timeRemoves = function(){
var start = (new Date()).getTime();
db.tester.remove();//再次测试代替用db.tester.drop();
db.tester.findOne();
var timeDiff = (new Date()).getTime() - start;
print("Remove took:"+timeDiff+"ms");
}
timeRemoves();

更新文档

文档替换
使用修改器

通常文档只会有一部分要更新。可以使用原子性的更新修改器update modifier
db.analytics.update({"url":"www.example.com"},{"$inc":{"pageviews":1}})
使用修改器时,"_id"的值不能改变。

"$set"修改器

要想添加喜欢的书籍进去,可以使用"$set":
db.users.update({"_id":ObjectId("4b25......123a")},{"$set":{"favorite book":"War and Peace"}})
用$set甚至可以修改键的类型,例如将"favorite book"的值变成数组:
db.users.update({"_id":ObjectId("4b25......123a")},{"$set":{"favorite book":["Book 1","Book 2","Book 3"]}})
也可以用"$unset"将这个键完全删除:
db.users.update({"name":"Joe")},{"$unset":{"favorite book":1}})
也可以用"$set"修改内嵌文档
db.blog.posts.update({"author.name":"joe"},{"$set":{"author.name":"joe schmoe"}})
增加、修改或删除键时,应该使用$修改器。

增加和减少

"$inc"修改器用来增加已有键的值,或者该键不存在那就创建一个。
db.games.update({"game":"pinball","user":"joe"},{"$inc":{"score":50}})
"$inc"只能用于整型、长整型或双精度浮点型的值。
"$inc"键的值必须为数字,不能使用字符串、数组或其他非数字的值。否则会提示"Modifier "$inc" allowed for numbers only"

数组修改器
添加元素

"$push"会向已有的数组末尾加入一个元素,要是没有就创建一个新的数组。
db.blog.posts.update({"title":"a blog"},{"$push":{"comments":{"name":"joe","email":"joe@example.com","content":"very good"}}})
使用"$each"子操作符,可以通过一次"$push"操作添加多个值。
可以将"$slice"和"$push"组合在一起使用,这样就可以保证数组不会超出设定好的最大长度。
db.movies.update({"genre":"honor"},{"$push":{"top10":{"$each":["movie 1","movie 2"],"$slice":-10}}})
最后,可以在清理元素之前使用"$sort",只要向数组中添加子对象就需要清理。
db.movies.find({"genre":"horror"},{"push":{"top10":{"$each":[{"name":"movie 1","rating":6.5},{"name":"movie 2","rating":4.3}],"$slice":-10,"$sort":{"rating":-1}}}})

将数组作为数据集使用

如果想将数组作为数据集使用,保证数组内的元素不会重复。可以在查询文档中用"$ne"(not exist的缩写)来实现。例如,要是作者不在引文列表中,就添加进去,可以这么做:
db.papers.update({"authors cited":{"$ne":"Richie"}},{"$push":{"authors cited":"Richie"}})
添加新地址时,用"$addToSet"可以避免插入重复地址:
db.users.update({"_id":ObjectId("a123...321a")},{"$addToSet":{"emails":"joe@mail.com"}})
将"$addToSet"和"$each"组合起来,可以添加多个不同的值,而用"$ne"和"$push"组合就不能实现。
db.users.update({"_id":ObjectId("a123...321a")},{"$addToSet":{"emails":{"$each":["jane@apple.com","jay@gmail.com","jason@qq.com"]}}})

删除元素
若是把数组看成队列或栈,可以用"$pop"。{"$pop":{"key":1}} 从数组末尾删除一个元素,{"$pop":{"key":-1}} 则从头部删除。
基于位置的数组修改器

MongoDB提供了定位操作符"$",用来定位查询文档已经匹配到的数组元素,并进行更新。
db.blog.update({"comments.author":"John"},{"$set":{"comments.$.author":"Jim"}})

修改器速度

$inc能就地修改,所以非常快。而数组修改器可能会改变文档的大小,就会慢一些。
当文档插入到MongoDB中时,依次插入的文档在磁盘的位置是相邻的。因此,如果一个文档变大了,原先的位置就放不下这个文档了,这个文档就会被移动到集合中的另一个位置。
MongoDB不得不移动一个文档时,它会修改集合的填充因子padding-factor。填充因子是MongoDB为每个新文档预留的增长空间。

"x":"a""x":"b""x":"c"
最初文档之间没有多余的空间

"x":"a""x":"b""x":"c"
如果一个文档因为体积变大而不得不进行移动,它原先占用的空间就闲置了,而且填充因子会增加。

"x":"a""x":"c""x":"bbb""x":"d""x":"e""x":"f"
之后插入的新文档都会拥有填充因子指定大小的增长空间。如果在之后的插入中不再发生文档移动,填充因子会逐渐变小。

写作本书时,MongoDB仍然不能很好地重用空白空间,因此频繁移动文档会产生大量空的数据文件。
extend a:7fabcd was empty,skipping ahead.这个消息提示本身没什么影响,但是他指出你当前拥有太多的碎片,可能需要进行压缩。
可以使用usePowerOf2Sizes选项以提高磁盘复用率。
db.runCommand({"collMod":collectionName,"usePowerOf2Sizes":true})
在已有的集合上运行这个命令或者更改这个选项的值不会对现有数据产生影响。

upsert
upsert非常方便,同一套代码既可以用于创建文档又可以用于更新文档。
update的第3个参数表示这是一个upsert
db.analytics.update({"url":"/blog"},{"$inc":{"previews":1}},true)

更新多个文档

默认情况下,更新只能对符合匹配条件的第一个文档执行操作。要更新所有匹配的文档,可以将update的第 4个参数设置为true。db.users.update({"birthday":"10/13/1978"},{"$set":{"gift":"Happy"}},false,true)
想要知道多文档更新到底更新了多少文档,可以运行getLastError命令(可以理解为"返回最后一次操作的相关信息")。键"n"的值就是被更新文档的数量。db.runCommand({getLastError:1})

返回被更新的文档
通过findAndModify命令得到被更新的文档。

写入安全机制

写入安全Write Concern是一种客户端设置,用于控制写入的安全级别。
两种最基本的写入安全机制:应答式写入acknowledged write和非应答式写入unacknowledged write。
shell与客户端程序对非应答式写入的实际支持不一样:shell在执行非应答式写入后,会检查最后一个操作是否成功。如果在集合上执行了一些列无效操作后,最后执行了一个有效操作,shell并不会提示有错误发生。
可以调用getLastError手动强制在shell中进行检查。
在默认写入安全机制发生变化前,任何语言都没有使用MongoClient作为类名,所以如果你的代码使用了这个类名,说明你的代码是写入安全的。
如果使用的连接不是MongoClient,应在必要时将旧代码中的非应答式写入改成应答式写入。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: