好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

mongodb 修改器($inc/$set/$unset/$push/$pop/upsert)

对于文档的更新除替换外,针对某个或多个文档只需要部分更新可使用原子的更新修改器,能够高效的进行文档更新。更新修改器是中特殊的键,
用来指定复杂的操作,比如增加、删除或者调整键,还可能是操作数组或者内嵌文档。

1.$inc

这个修改器干什么使的呢?看看下面示例的具体操作后的结果即可知道。
示例文档:{"uid":"201203","type":"1",size:10}

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

> db.b. insert ({ "uid" : "201203" , "type" : "1" , size :10})

> db.b.find()

{ "_id" : ObjectId( "5003b6135af21ff428dafbe6" ), "uid" : "201203" , "type" : "1" ,

"size" : 10 }

> db.b. update ({ "uid" : "201203" },{ "$inc" :{ "size" : 1}})

> db.b.find()

{ "_id" : ObjectId( "5003b6135af21ff428dafbe6" ), "uid" : "201203" , "type" : "1" ,

"size" : 11 }

> db.b. update ({ "uid" : "201203" },{ "$inc" :{ "size" : 2}})

> db.b.find()

{ "_id" : ObjectId( "5003b6135af21ff428dafbe6" ), "uid" : "201203" , "type" : "1" ,

"size" : 13 }

> db.b. update ({ "uid" : "201203" },{ "$inc" :{ "size" : -1}})

> db.b.find()

{ "_id" : ObjectId( "5003b6135af21ff428dafbe6" ), "uid" : "201203" , "type" : "1" ,

"size" : 12 }

得出结论:修改器$inc可以对文档的某个值为数字型(只能为满足要求的数字)的键进行增减的操作。
(这里有个问题:上篇中说到更新默认只对满足条件的记录集中第一个文档进行更新,那么使用$inc修改器之后,还是一样吗?)

2.$set

用来指定一个键并更新键值,若键不存在并创建。来看看下面的效果:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

> db.a.findOne({ "uid" : "20120002" , "type" : "3" })

{ "_id" : ObjectId( "500216de81b954b6161a7d8f" ), "desc" : "hello world2!" , "num"

: 40, "sname" : "jk" , "type" : "3" , "uid" : "20120002" }

--size键不存在的场合

> db.a. update ({ "uid" : "20120002" , "type" : "3" },{ "$set" :{ "size" :10}})

> db.a.findOne({ "uid" : "20120002" , "type" : "3" })

{ "_id" : ObjectId( "500216de81b954b6161a7d8f" ), "desc" : "hello world2!" , "num"

: 40, "size" : 10, "sname" : "jk" , "type" : "3" , "uid" : "20120002" }

--sname键存在的场合

> db.a. update ({ "uid" : "20120002" , "type" : "3" },{ "$set" :{ "sname" : "ssk" }})

> db.a.find()

{ "_id" : ObjectId( "500216de81b954b6161a7d8f" ), "desc" : "hello world2!" , "num"

: 40, "size" : 10, "sname" : "ssk" , "type" : "3" , "uid" : "20120002" }

{ "_id" : ObjectId( "50026affdeb4fa8d154f8572" ), "desc" : "hello world1!" , "num"

: 50, "sname" : "jk" , "type" : "1" , "uid" : "20120002" }

--可改变键的值类型

> db.a. update ({ "uid" : "20120002" , "type" : "3" },{ "$set" :{ "sname" :[ "Java" , ".net" , "c++" ]}})

> db.a.findOne({ "uid" : "20120002" , "type" : "3" })

{

   "_id" : ObjectId( "500216de81b954b6161a7d8f" ),

   "desc" : "hello world2!" ,

   "num" : 40,

   "size" : 10,

   "sname" : [

     "java" ,

     ".net" ,

     "c++"

   ],

   "type" : "3" ,

   "uid" : "20120002"

}

对于内嵌的文档,$set又是如何进行更新的内嵌的文档的呢,请看下面的示例:
示例文档:{"name":"toyota","type":"suv","size":{"height":10,"width":5,"length":15}}

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

> db.c.findOne({ "name" : "toyota" })

{

   "_id" : ObjectId( "5003be465af21ff428dafbe7" ),

   "name" : "toyota" ,

   "type" : "suv" ,

   "size" : {

     "height" : 10,

     "width" : 5,

     "length" : 15

   }

}

> db.c. update ({ "name" : "toyota" },{ "$set" :{ "size.height" :8}})

> db.c.findOne({ "name" : "toyota" })

{

   "_id" : ObjectId( "5003be465af21ff428dafbe7" ),

   "name" : "toyota" ,

   "type" : "suv" ,

   "size" : {

     "height" : 8,

     "width" : 5,

     "length" : 15

   }

}

> db.c. update ({ "name" : "toyota" },{ "$set" :{ "size.width" :7}})

> db.c.findOne({ "name" : "toyota" })

{

   "_id" : ObjectId( "5003be465af21ff428dafbe7" ),

   "name" : "toyota" ,

   "type" : "suv" ,

   "size" : {

     "height" : 8,

     "width" : 7,

     "length" : 15

   }

}

可见:对于内嵌文档在使用$set更新时,使用"."连接的方式。

3.$unset

从字面就可以看出其意义,主要是用来删除键。
示例操作效果如下:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

> db.a. update ({ "uid" : "20120002" , "type" : "3" },{ "$unset" :{ "sname" :1}})

> db.a.findOne({ "uid" : "20120002" , "type" : "3" })

{

   "_id" : ObjectId( "500216de81b954b6161a7d8f" ),

   "desc" : "hello world2!" ,

   "num" : 40,

   "size" : 10,

   "type" : "3" ,

   "uid" : "20120002"

}

> db.a. update ({ "uid" : "20120002" , "type" : "3" },{ "$unset" :{ "num" :0}})

> db.a.findOne({ "uid" : "20120002" , "type" : "3" })

{

   "_id" : ObjectId( "500216de81b954b6161a7d8f" ),

   "desc" : "hello world2!" ,

   "size" : 10,

   "type" : "3" ,

   "uid" : "20120002"

}

> db.a. update ({ "uid" : "20120002" , "type" : "3" },{ "$unset" :{ "size" :-1}})

> db.a.findOne({ "uid" : "20120002" , "type" : "3" })

{

   "_id" : ObjectId( "500216de81b954b6161a7d8f" ),

   "desc" : "hello world2!" ,

   "type" : "3" ,

   "uid" : "20120002"

}

> db.a. update ({ "uid" : "20120002" , "type" : "3" },{ "$unset" :{ "desc" : "sssssss" }})

> db.a.findOne({ "uid" : "20120002" , "type" : "3" })

{

   "_id" : ObjectId( "500216de81b954b6161a7d8f" ),

   "type" : "3" ,

   "uid" : "20120002"

}

得出结论:使用修改器$unset时,不论对目标键使用1、0、-1或者具体的字符串等都是可以删除该目标键。

4.数组修改器--$push

示例操作效果如下:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

> db.c.find()

{ "_id" : ObjectId( "5003be465af21ff428dafbe7" ), "name" : "toyota" , "type" : "suv" ,

"size" : { "height" : 8, "width" : 7, "length" : 15 } }

--先push一个当前文档中不存在的键title

> db.c. update ({ "name" : "toyota" },{$push:{ "title" : "t1" }})

> db.c.find()

{ "_id" : ObjectId( "5003be465af21ff428dafbe7" ), "name" : "toyota" , "size" : { "height" : 8,

  "width" : 7, "length" : 15 }, "title" : [ "t1" ], "type" : "suv" }

 

--再向title中push一个值

> db.c. update ({ "name" : "toyota" },{$push:{ "title" : "t2" }})

> db.c.find()

{ "_id" : ObjectId( "5003be465af21ff428dafbe7" ), "name" : "toyota" , "size" : { "height" : 8,

  "width" : 7, "length" : 15 }, "title" : [ "t1" , "t2" ], "type" : "suv" }

--再向title中push一个值

> db.c. update ({ "name" : "toyota" },{$push:{ "title" : "t2" }})

> db.c.find()

{ "_id" : ObjectId( "5003be465af21ff428dafbe7" ), "name" : "toyota" , "size" : { "height" : 8,

  "width" : 7, "length" : 15 }, "title" : [ "t1" , "t2" , "t2" ], "type" : "suv" }

--再向一个已经存在的键值非数组类型的键push一个值

> db.c. update ({ "name" : "toyota" },{$push:{ "size.height" :10}})

Cannot apply $push/$pushAll modifier to non-array

> db.c. update ({ "name" : "toyota" },{$push:{ "name" : "ddddddd" }})

Cannot apply $push/$pushAll modifier to non-array

得出结论:$push--向文档的某个数组类型的键添加一个数组元素,不过滤重复的数据。添加时键存在,要求键值类型必须是数组;键不存在,则创建数组类型的键。

5.数组修改器--$ne/$addToSet

主要给数组类型键值添加一个元素时,避免在数组中产生重复数据,$ne在有些情况是不通行的。

?

1

2

3

4

5

6

7

8

> db.c. update ({ "title" : {$ne: "t2" }},{$push:{ "title" : "t2" }})

> db.c.find()

{ "_id" : ObjectId( "5003be465af21ff428dafbe7" ), "name" : "toyota" , "size" : { "height" : 8,

  "width" : 7, "length" : 15 }, "title" : [ "t1" , "t2" , "t2" ], "type" : "suv" }

> db.c. update ({ "name" : "toyota" },{$addToSet:{ "title" : "t2" }})

> db.c.find()

{ "_id" : ObjectId( "5003be465af21ff428dafbe7" ), "name" : "toyota" , "size" : { "height" : 8,

  "width" : 7, "length" : 15 }, "title" : [ "t1" , "t2" , "t2" ], "type" : "suv" }

6.数组修改器--$pop、$pull

$pop从数组的头或者尾删除数组中的元素,示例如下:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

{ "_id" : ObjectId( "5003be465af21ff428dafbe7" ), "name" : "toyota" , "size" : { "height" : 8,

  "width" : 7, "length" : 15 }, "title" : [ "t1" , "t2" , "t3" , "t4" ], "type" : "suv" }

--从数组的尾部删除 1

> db.c. update ({ "name" : "toyota" },{$pop:{ "title" :1}})

> db.c.find()

{ "_id" : ObjectId( "5003be465af21ff428dafbe7" ), "name" : "toyota" , "size" : { "height" : 8,

  "width" : 7, "length" : 15 }, "title" : [ "t1" , "t2" , "t3" ], "type" : "suv" }

--从数组的头部 -1

> db.c. update ({ "name" : "toyota" },{$pop:{ "title" :-1}})

> db.c.find()

{ "_id" : ObjectId( "5003be465af21ff428dafbe7" ), "name" : "toyota" , "size" : { "height" : 8,

  "width" : 7, "length" : 15 }, "title" : [ "t2" , "t3" ], "type" : "suv" }

--从数组的尾部删除 0

> db.c. update ({ "name" : "toyota" },{$pop:{ "title" :0}})

> db.c.find()

{ "_id" : ObjectId( "5003be465af21ff428dafbe7" ), "name" : "toyota" , "size" : { "height" : 8,

  "width" : 7, "length" : 15 }, "title" : [ "t2" ], "type" : "suv" }

 

$pull从数组中删除满足条件的元素,示例如下:

{ "_id" : ObjectId( "5003be465af21ff428dafbe7" ), "name" : "toyota" , "size" : { "height" : 8,

  "width" : 7, "length" : 15 }, "title" : [ "t1" , "t2" , "t2" , "t3" ], "type" : "suv" }

 

> db.c. update ({ "name" : "toyota" },{$pull:{ "title" : "t2" }})

> db.c.find()

{ "_id" : ObjectId( "5003be465af21ff428dafbe7" ), "name" : "toyota" , "size" : { "height" : 8,

  "width" : 7, "length" : 15 }, "title" : [ "t1" , "t3" ], "type" : "suv" }

7.数组的定位修改器

在需要对数组中的值进行操作的时候,可通过位置或者定位操作符("$").数组是0开始的,可以直接将下标作为键来选择元素。
示例如下:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

{ "uid" : "001" ,comments:[{ "name" : "t1" , "size" :10},{ "name" : "t2" , "size" :12}]}

> db.c.find({ "uid" : "001" })

{ "_id" : ObjectId( "5003da405af21ff428dafbe8" ), "uid" : "001" , "comments" : [ {

"name" : "t1" , "size" : 10 }, { "name" : "t2" , "size" : 12 } ] }

> db.c. update ({ "uid" : "001" },{$inc:{ "comments.0.size" :1}})

> db.c.find({ "uid" : "001" })

{ "_id" : ObjectId( "5003da405af21ff428dafbe8" ), "uid" : "001" , "comments" : [ {

"name" : "t1" , "size" : 11 }, { "name" : "t2" , "size" : 12 } ] }

> db.c. update ({ "comments.name" : "t1" },{$ set :{ "comments.$.size" :1}})

> db.c.find({ "uid" : "001" })

{ "_id" : ObjectId( "5003da405af21ff428dafbe8" ), "uid" : "001" , "comments" : [ {

"name" : "t1" , "size" : 1 }, { "name" : "t2" , "size" : 12 } ] }

--若为多个文档满足条件,则只更新第一个文档。

8.upsert

upsert是一种特殊的更新。当没有符合条件的文档,就以这个条件和更新文档为基础创建一个新的文档,如果找到匹配的文档就正常的更新。
使用upsert,既可以避免竞态问题,也可以减少代码量(update的第三个参数就表示这个upsert,参数为true时)

?

1

2

3

4

5

6

7

8

> db.c.remove()

> db.c. update ({ "size" :11},{$inc:{ "size" :3}})

> db.c.find()

> db.c. update ({ "size" :11},{$inc:{ "size" :3}}, false )

> db.c.find()

> db.c. update ({ "size" :11},{$inc:{ "size" :3}}, true )

> db.c.find()

{ "_id" : ObjectId( "5003ded6c28f67507a6df1de" ), "size" : 14 }

9.save函数

1.可以在文档不存在的时候插入,存在的时候更新,只有一个参数文档。
2.要是文档含有"_id",会调用upsert。否则,会调用插入。

?

1

2

3

4

5

6

7

8

9

10

> db.a.find()

{ "_id" : ObjectId( "50026affdeb4fa8d154f8572" ), "desc" : "hello world1!" , "num" : 50,

  "sname" : "jk" , "type" : "1" , "uid" : "20120002" }

> var o = db.a.findOne()

> o.num = 55

55

> db.a.save(o)

> db.a.find()

{ "_id" : ObjectId( "50026affdeb4fa8d154f8572" ), "desc" : "hello world1!" , "num" : 55,

  "sname" : "jk" , "type" : "1" , "uid" : "20120002" }

原文链接:http://blog.csdn.net/mcpang/article/details/7752736

查看更多关于mongodb 修改器($inc/$set/$unset/$push/$pop/upsert)的详细内容...

  阅读:34次