MongoDB中数组类型相关的操作
本文内容纲要:
-概述
-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
为2
anda
大于等于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