首页 文章资讯内容详情

MongoDB中数组类型相关的操作

2026-05-31 10 花语

本文内容纲要:

-概述 -1.$push操作符 -2.$pop操作符 -3.$pull操作符 -4.$addToSet

概述

在MongoDB的模式中,我们经常将一些数据存储到数组类型中,即我们常见的嵌套模式设计的一种实现方式。数组的这种设计实现方式在关系数据库中是没有或者说不常见的。所以,通过本文我们来梳理一下MongoDB的数组的相关操作。关于数组的操作可以分成两类,一类是数组操作符,另一个是数组运算修饰符。

数组操作符

操作符 实现功能 $ 根据查询选择器定位要更新的文档 $push 添加值到数组中 $pushAll 添加数组到一个数组中。(将被$rach取代) $addToSet

添加值到数组中,重复了也不处理

$pop 从数组中删除第一个或者最后一个值。 $pull 从数组中删除匹配查询条件的值。 $pullAll 从数组中删除多个值。

数组运算修饰符

修饰符 实现功能 $each 与$push和$addToSet一起使用来操作多个值。 $slice 与$push和$each一起使用来缩小更新后数组的大小。 $sort 与$push、$each、$slice一起来排序数组中的子文档。

1.$push操作符

1.1语法及功能描述

$push主要用来向数组中添加元素。

语法:

{$push:{<field1>:<value1>,...}}

默认情况下,它会在数组尾部添加一个单独的元素。

1.2操作案例

假如我们有一个学生成绩的集合studentscore,其文档格式如下:

{"_id":1,"name":"xiaoming","score":[{"math":99,"english":89}]} {"_id":2,"name":"xiaohong","score":[{"math":98,"english":96}]}

其中的需求为,更新_id为1的文档记录,在分数数组的字段上,添加物理学的成绩,修改代码为

db.studentscore.update({_id:1},{$push:{score:{"physics":100}}})

修改后,结果查询如下:

{"_id":1,"name":"xiaoming","score":[{"math":99,"english":89},{"physics":100}]} {"_id":2,"name":"xiaohong","score":[{"math":98,"english":96}]} 1.3结合$each修饰符,批量插入

如果一次将多个值添加到数组中,可结合数组修改符$each一起使用。

例如,我们将小红的(_id=2)的物理成绩、化学成绩、生物成绩一起添加到文档中。执行的语句如下:

db.studentscore.update({_id:2}, { $push:{ score:{ $each:[{"physics":100},{"chemistry":90},{"biology":99}] } } } )

查询的结果如下:

{"_id":1,"name":"xiaoming","score":[{"math":99,"english":89},{"physics":100}]} {"_id":2,"name":"xiaohong","score":[{"math":98,"english":96},{"physics":100},{"chemistry":90},{"biology":99}]} 1.4数组修饰符$sort和$slice的使用

前面讲了$each数组运算修饰符,那我们再举一个例子,将剩余的两个修饰符一起讲解了好了($sort和$slice)

例如,我们有文档记录如下:

{ "_id":5, "quizzes":[ {"wk":1,"score":10}, {"wk":2,"score":8}, {"wk":3,"score":5}, {"wk":4,"score":6} ] }

现在我们,有个需求,就是首先向文档的quizzes数组字段,追加三个记录,然后,我们再按照score排序,选取数组中的前三个元素。

db.students.update( {_id:5}, { $push:{ quizzes:{ $each:[{wk:5,score:8},{wk:6,score:7},{wk:7,score:6}], $sort:{score:-1}, $slice:3 } } } )

更新后的结果显示如下:

{ "_id":5, "quizzes":[ {"wk":1,"score":10}, {"wk":2,"score":8}, {"wk":5,"score":8} ] }

$slice操作修饰符是在MongoDB2.4里添加的,其目的是方便管理经常更新的数组。当向数组添加值但是不想数组太大的时候,这个操作符非常有用。它必须与$push、$each操作符一起使用,允许用来剪短数组的大小、删除旧的值。

与$slice操作修饰符很像,MongoDB2.4新增了$sort操作修饰符,帮助更新数组。当使用$push和$slice时,有时候要先排序再删除它们。

2.$pop操作符

2.1语法及功能描述

$pop操作符可以实现从数组中删除第一个或者是最好一个元素。

{$pop:{<field>:<-1|1>,...}}

参数为-1,代表要删除数组中的第一个元素;参数为1,代表要删除数组中的最后一个元素。

2.2操作案例

例如集合students中有以下文档:

{_id:1,scores:[8,9,10]}

我们的需求是要把数组中的第一个元素(成绩为8)移除,SQL语句如下:

db.students.update({_id:1},{$pop:{scores:-1}})

更新后,文档如下

{_id:1,scores:[9,10]}

继续演示,如果在现有的基础上,我们需要进一步把数组的最后一个元素移除(成绩为10),更新的sQL如下:

db.students.update({_id:1},{$pop:{scores:1}})

查询结果如下:

{_id:1,scores:[9]}

3.$pull操作符

3.1语法及功能描述

$pull是$pop的复杂形式。使用$pull,可以通过值精确指定要删除的元素。

语法格式

{$pull:{<field1>:<value|condition>,<field2>:<value|condition>,...}} 3.2操作案例 3.2.1移除数组中等于指定值的元素

测试文档如下:

{ _id:1, fruits:["apples","pears","oranges","grapes","bananas"], vegetables:["carrots","celery","squash","carrots"] } { _id:2, fruits:["plums","kiwis","oranges","bananas","apples"], vegetables:["broccoli","zucchini","carrots","onions"] }

操作要求是将数组字段fruits中的"apples"and"oranges"移除,还要将vegetables数组字段中的"carrots"移除,其更新语句如下:

db.stores.update( {}, {$pull:{fruits:{$in:["apples","oranges"]},vegetables:"carrots"}}, {multi:true} )

更新后的结果如下:

{ "_id":1, "fruits":["pears","grapes","bananas"], "vegetables":["celery","squash"] } { "_id":2, "fruits":["plums","kiwis","bananas"], "vegetables":["broccoli","zucchini","onions"] }

此时,集合文档中,fruit的数组字段没有apples也没有``oranges,vegetables数组字段也没有了carrots。

3.2.2移除数组中满足指定条件的元素

假如我们有一个profiles的集合,其文档格式如下:

{_id:1,votes:[3,5,6,7,7,8]}

我们要把votes大于等于6的元素移除,其语句如下:

db.profiles.update({_id:1},{$pull:{votes:{$gte:6}}})

更新后的结果如下:

{_id:1,votes:[3,5]} 3.2.3移除数组中内嵌子文档(即此时数组元素是子文档,每一个{}中的内容是一个数组元素)

假设我们有一个关于调查的集合survey,其数据如下:

{ _id:1, results:[ {item:"A",score:5}, {item:"B",score:8,comment:"Stronglyagree"} ] } { _id:2, results:[ {item:"C",score:8,comment:"Stronglyagree"}, {item:"B",score:4} ] }

需求是将score为8并且item为"B"的元素移除

db.survey.update( {}, {$pull:{results:{score:8,item:"B"}}}, {multi:true} )

更新后的文档如下:

{ "_id":1, "results":[{"item":"A","score":5}] } { "_id":2, "results":[ {"item":"C","score":8,"comment":"Stronglyagree"}, {"item":"B","score":4} ] } 3.2.4如果数组类型的元素还内嵌一个数组(数组包数组),就要特别小心了。

此时就要用到$elemMatch操作符。

例如文档格式如下:

{ _id:1, results:[ {item:"A",score:5,answers:[{q:1,a:4},{q:2,a:6}]}, {item:"B",score:8,answers:[{q:1,a:8},{q:2,a:9}]} ] } { _id:2, results:[ {item:"C",score:8,answers:[{q:1,a:8},{q:2,a:7}]}, {item:"B",score:4,answers:[{q:1,a:0},{q:2,a:8}]} ] }

需要将results数组字段移除,移除的条件是results数组字段中的answers字段,符合q为2anda大于等于8。

db.survey.update( {}, {$pull:{results:{answers:{$elemMatch:{q:2,a:{$gte:8}}}}}}, {multi:true} )

更新后的数据如下:

{ "_id":1, "results":[ {"item":"A","score":5,"answers":[{"q":1,"a":4},{"q":2,"a":6}]} ] } { "_id":2, "results":[ {"item":"C","score":8,"answers":[{"q":1,"a":8},{"q":2,"a":7}]} ] }

4.$addToSet

4.1语法及功能描述

使用$addToSet也会往数组后面添加值,但是它比较特殊:它只会添加数组里不存在的值。

{$addToSet:{<field1>:<value1>,...}} 4.2操作案例

假如有一个集合inventory格式如下

{_id:1,item:"polarizing_filter",tags:["electronics","camera"]}

我们希望向向字段tags数组,添加一个元素accessories,则更新语句如下:

db.inventory.update( {_id:1}, {$addToSet:{tags:"accessories"}} )

更新后的结果为

{"_id":1,"item":"polarizing_filter","tags":["electronics","camera","accessories"]}

如果想批量的增加如果元素,我们可以结合$each操作符一起使用。

例如以下文档

{_id:2,item:"cable",tags:["electronics","supplies"]}

我们想在字段tags数组,添加元素"camera","electronics","accessories",则更新语句如下:

db.inventory.update( {_id:2}, {$addToSet:{tags:{$each:["camera","electronics","accessories"]}}} )

更新后的结果如下:

{ _id:2, item:"cable", tags:["electronics","supplies","camera","accessories"] } 4.3注意点

需要注意是,如果添加的元素是数组格式,则会将新添加的元素保留为数组(将会出现数组嵌套数组)

例如

{_id:1,letters:["a","b"]}

执行的语句如下:

db.test.update( {_id:1}, {$addToSet:{letters:["c","d"]}} )

查询结构显示为

{_id:1,letters:["a","b",["c","d"]]}

本文部分例子来自官网及网络,在此感谢。

本文版权归作者所有,未经作者同意不得转载**,**谢谢配合!!!

本文内容总结:概述,1.$push操作符,2.$pop操作符,3.$pull操作符,4.$addToSet,

原文链接:https://www.cnblogs.com/xuliuzai/p/10331524.html