学习体会
Posted 令狐葱dennis
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了学习体会相关的知识,希望对你有一定的参考价值。
前言
最近在学习Mongodb权威指南,其中有些内容,还是比较难理解,和大家分享一下。
1、数组update
update用于更新文档,更新操作分成两阶段完成,首先找到目标文档,然后修改目标文档。
涉及到数组操作的operator有以下四个:
示例集合 students :
"name": "Tom",
"gender": "male",
"class_id": "300",
push:push向数组中添加一个元素,一次添加多个元素需要配合each
(1)向集合中加入字段选修课 :
1.db.students.update("name":"Tom", $push : "optional lesson": "math")
(2)向学生"Tom"的"optional lesson"字段加入多个元素:
db.students.update("name":"Tom", $push : "optional lesson": $each: ["math", "Chinese", "Spanish"])
值得注意的是,push操作是允许添加重复值的,因此上面的语句如下图所示:
使用addToSet会将待插入元素和文档中的数组元素进行比较,实现去重添加的效果。
(3) 向学生"Tom"的"optional lesson"字段加入多个元素,并去重:
db.students.update("name":"Tom", $addToSet : "optional lesson": $each: ["math", "Chinese", "Spanish"])
可以看到这样,就达到了去重的效果
2、upsert
在使用update的时候,可能存在没有找到指定文档的情况,如果在这种情况中,我们想让Mongodb创建出一个默认的文档的话就可以使用upsert。
db.test.update("count": 25, $inc: "count": 3, true)
3、修改器速度
这一节主要是讲了填充因子和空间分配大小在文档更新时的作用。
每次执行更新操作,都有可能增大文档的大小,如果该文档的前后连续的物理位置都存储有其他文档,那么当我们写入该文档的时候就会把它移动到集合的末尾。
每次执行这样的移动操作的时候,mongodb都会增加集合的填充因子(padding factor)。下一次执行插入操作时,给新文档分配的空间: alloc_space =
actual_space * padding_factor。通过设置padding factor减少了文档搬移的可能性,从而减少了硬盘IO的发生。同时这里也是局部性原理的体现,如果频繁发生
文档的搬移说明当前文档的更新操作比较频繁,后续插入的新文档大概率也会出现搬移的操作。如下图,b:2的更新操作导致文档被搬移到集合末尾,从而导致
填充因子增加(>1)。
从前文可以看到每次发生文档的搬移操作之后,在原位置就会出现一段空闲空间(free space)。如果没有特殊的分配策略的话,这些空闲空间的大小就是原文档的
大小,意味着这些空间的大小是相当随机的,也就意味着新插入的文档大概率会无法利用这些空闲的空间,这些虽然空闲但是没有办法被利用的空间被称作碎片。
为了减少空间碎片,我们可以采用usePowerOf2Sizes。
db.runCommand("collMod" : collectionName, "usePowerOf2Sizes": true)
使用该选项之后,每次分配空间是2的幂次。这样留下的空闲空间都会是fixed-size(固定空间),而不是随机大小。从而减少了碎片的产生。
4、数组find
$all
all用来匹配数组中的多个值。假设我们有一个如下的文档:
_id: ObjectId("621b3d2a7c51445f6727e045"),
fruits: [ \'apple\', \'banana\', \'pineapple\', \'orange\' ]
可以使用如下的语句去搜索指定文档:
db.test.find("fruits": $all: ["apple", "banana"])
$slice
find的第二个参数可以指定返回的键---find(, "return_key": 1)。使用slice语句替换1,可以指定需要返回的数组元素。
test> db.test.find()
[
_id: ObjectId("621b3d2a7c51445f6727e045"),
fruits: [ \'apple\', \'banana\', \'pineapple\', \'orange\' ]
]
test> db.test.find(, "fruits": $slice: 1)
[ _id: ObjectId("621b3d2a7c51445f6727e045"), fruits: [ \'apple\' ] ]
返回一个匹配的元素
使用$操作符可以返回第一个满足查询要求的数组元素
db.restaurants.find("grades.grade": "A", "grades.$": 1)
$elemMatch
使用elemMatch之后,查询条件必须满足每一个数组元素,才会返回。如下图所示,在第一个find中使用了elemMatch返回的结果中是每个元素都满足
80<= elm <=85。而第二个find,由于88是满足条件的,所以也返回了这个数组。
scores> db.scores.find()
[
_id: 1, results: [ 82, 85, 88 ] ,
_id: 2, results: [ 75, 88, 89 ]
]
scores> db.scores.find( results: $elemMatch: $gte: 80, $lt: 85 )
[ _id: 1, results: [ 82, 85, 88 ] ]
scores> db.scores.find( results: $gte: 80, $lt: 85 )
[
_id: 1, results: [ 82, 85, 88 ] ,
_id: 2, results: [ 75, 88, 89 ]
]
以上是关于学习体会的主要内容,如果未能解决你的问题,请参考以下文章