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" ] }