MongoDB查询(2)——数组查询[六]
MongoDB查询数组
一、概述
MongoDB查询数组与查询标量值是一样的,例如,有一个水果列表,如下所示:
> db.food.find() { "_id" : "001", "fruits" : [ "苹果", "香蕉", "橘子" ] } { "_id" : "002", "fruits" : [ "苹果", "梨子", "橘子", "桃子" ] } { "_id" : "003", "fruits" : [ "圣女果", "梨子", "橘子", "桃子" ] }
现在我要查询含有苹果的食品,实例如下:
> db.food.find({"fruits":"苹果"}) { "_id" : "001", "fruits" : [ "苹果", "香蕉", "橘子" ] } { "_id" : "002", "fruits" : [ "苹果", "梨子", "橘子", "桃子" ] }
MongoDB查询数组时,查询条件会与每个元素进行比较,如果匹配上了,就算符合条件
二、"$all"操作符
如果需要通过多个元素来匹配数组,就要用"$all"了。
还是下面这个水果列表:
> db.food.find() { "_id" : "001", "fruits" : [ "苹果", "香蕉", "橘子" ] } { "_id" : "002", "fruits" : [ "苹果", "梨子", "橘子", "桃子" ] } { "_id" : "003", "fruits" : [ "圣女果", "梨子", "橘子", "桃子" ] }
参考实例一:查询水果列表中既有苹果又有桃子的食品
> db.food.find({"fruits":{"$all":["苹果","桃子"]}}) --这是AND的关系 { "_id" : "002", "fruits" : [ "苹果", "梨子", "橘子", "桃子" ] }
这里的顺序没有任何关系。
数组都是可以通过下标访问的,MongoDB也不例外;
参考实例二:查询水果列表中下标为1的元素是梨子的食品
> db.food.find({"fruits.1":"梨子"}) { "_id" : "002", "fruits" : [ "苹果", "梨子", "橘子", "桃子" ] } { "_id" : "003", "fruits" : [ "圣女果", "梨子", "橘子", "桃子" ] }
三、"$size"操作符
这个"$size"非常有用,顾名思义就是查询特定长度的数组。
参考实例一:查询food集合中frutis数组包含3个元素的文档
> db.food.find({"fruits":{"$size":3}}) { "_id" : "001", "fruits" : [ "苹果", "香蕉", "橘子" ] }
查询一定长度范围内的文档时一种常见查询。"$size"并不能与其他查询条件(比如"$gt")组合使用;遇到这种业务怎么办?
答:遇到这种情况可以再文档中加一个size的键,每次往指定数组中添加一个元素就把size这个键的值加1;
参考实例如下:
原本更新语句如下:
db.food.update({"_id":"004"},{"$push":{"fruits":"苹果"}})
现在需要变成如下:
db.food.update({"_id":"004"},{"$push":{"fruits":"苹果"},"$inc":{"size":1}})
"$inc"自增长的速度非常快,对性能影响几乎微乎其微,这样建模以后就可以如下这么查询了
db.food.find({"size":{"$gt":3}}) --查询数组长度大于3的文档
温馨提示:这种技巧并不能与"$addToSet"(如果数组中已经存在该元素就不添加)操作符一起使用。
三、"$slice"操作符
find方法的第二个参数是可选的,可以指定需要返回的列,"$slice"操作符用来返回某个键匹配数组元素的一个子集
例如下面有这样一个文档
db.test.insert({"_id":"t001","lists":["aa","bb","cc","ee","ff","gg"]})
参考实例一:返回lists前3个元素
> db.test.find({},{"lists":{"$slice":3}}) { "_id" : "t001", "lists" : [ "aa", "bb", "cc" ] }
参考实例二:返回lists后3个元素
> db.test.find({},{"lists":{"$slice":-3}}) { "_id" : "t001", "lists" : [ "ee", "ff", "gg" ] }
参考实例三:从linsts中第2个元素开始,返回3个元素
> db.test.find({},{"lists":{"$slice":[2,3]}}) { "_id" : "t001", "lists" : [ "cc", "ee", "ff" ] }