本文将会介绍 MongoDB 中查找数组元素相关的运算符,包括 $size、$all 以及 $elemMatch。
$size 是一个数组查询运算符,可以判断文档的字段是否包含指定数量的元素。
$size 运算符的语法如下:
{ array_field: {$size: element_count} }
其中,array_field 是字段名,element_count 表示该字段包含的元素数量。
接下来的示例将会使用以下集合:
db.products.insertMany([
{ "_id" : 1, "name" : "xPhone", "price" : 799, "releaseDate" : ISODate("2011-05-14T00:00:00Z"), "spec" : { "ram" : 4, "screen" : 6.5, "cpu" : 2.66 }, "color" : [ "white", "black" ], "storage" : [ 64, 128, 256 ] },
{ "_id" : 2, "name" : "xTablet", "price" : 899, "releaseDate" : ISODate("2011-09-01T00:00:00Z"), "spec" : { "ram" : 16, "screen" : 9.5, "cpu" : 3.66 }, "color" : [ "white", "black", "purple" ], "storage" : [ 128, 256, 512 ] },
{ "_id" : 3, "name" : "SmartTablet", "price" : 899, "releaseDate" : ISODate("2015-01-14T00:00:00Z"), "spec" : { "ram" : 12, "screen" : 9.7, "cpu" : 3.66 }, "color" : [ "blue" ], "storage" : [ 16, 64, 128 ] },
{ "_id" : 4, "name" : "SmartPad", "price" : 699, "releaseDate" : ISODate("2020-05-14T00:00:00Z"), "spec" : { "ram" : 8, "screen" : 9.7, "cpu" : 1.66 }, "color" : [ "white", "orange", "gold", "gray" ], "storage" : [ 128, 256, 1024 ] },
{ "_id" : 5, "name" : "SmartPhone", "price" : 599, "releaseDate" : ISODate("2022-09-14T00:00:00Z"), "spec" : { "ram" : 4, "screen" : 9.7, "cpu" : 1.66 }, "color" : [ "white", "orange", "gold", "gray" ], "storage" : [ 128, 256 ] },
{ "_id" : 6, "name" : "xWidget", "spec" : { "ram" : 64, "screen" : 9.7, "cpu" : 3.66 }, "color" : [ "black" ], "storage" : [ 1024 ] }
])
以下示例使用 $size 运算符查找数组字段 color 包含两个元素的文档:
db.products.find({
color: {
$size: 2
}
}, {
name: 1,
color: 1
})
查询返回的文档如下:
{ "_id" : 1, "color" : [ "white", "black" ], "name" : "xPhone" }
以下示例同时使用了 $size 运算符和 $or 运算符查找数组字段 color 包含一个或者两个元素的文档:
db.products.find({
$or: [{
color: {
$size: 1
}
},
{
color: {
$size: 2
}
}
]
}, {
name: 1,
color: 1
})
查询返回的结果如下:
{ "_id" : 1, "color" : [ "white", "black" ], "name" : "xPhone" }
{ "_id" : 3, "color" : [ "blue" ], "name" : "SmartTablet" }
$all 是一个数组查询运算符,可以判断文档的字段是否包含指定的所有元素。
$all 运算符的语法如下:
{ <arrayField>: { $all: [element1, element2, ...]} }
如果 $all 运算符后面的数组为空,不会匹配任何文档。
如果 $all 运算符只有一个元素,应该使用表达式,而不是数组:
{ <arrayField>: element1 }
$all 运算符可以使用等价的 $and 运算符实现:
{ $and: [{ arrayField: element1}, {arrayField: element2} ]}
以下示例使用 $all 运算符查找 color 字段同时包含“black”和“white”两个元素的文档:
db.products.find({
color: {
$all: ["black", "white"]
}
}, {
name: 1,
color: 1
})
查询返回的结果如下:
{ "_id" : 1, "name" : "xPhone", "color" : [ "white", "black" ] }
{ "_id" : 2, "name" : "xTablet", "color" : [ "white", "black", "purple" ] }
上面的示例也可以使用 $and 运算符实现:
db.products.find({
$and: [
{color: "black"},
{color: "white"}
]
}, {
name: 1,
color: 1
})
$elemMatch 也是一个数组查询运算符,可以判断文档是否包含指定数组字段,并且该字段至少包含一个满足条件的元素。
$elemMatch 运算符的语法如下:
{ <arrayField>: {$elemMatch: { <query1>, <query2>, ...} } }
注意,$elemMatch 运算符不支持 $where 表达式或者 $text 查询表达式。
以下示例使用 $elemMatch 运算符查询 products 集合中的文档:
db.products.find({
storage: {
$elemMatch: {
$lt: 128
}
}
}, {
name: 1,
storage: 1
});
查询返回了数组字段 storage 中至少包含一个小于 128 的元素的文档:
[
{ _id: 1, name: 'xPhone', storage: [ 64, 128, 256 ] },
{ _id: 3, name: 'SmartTablet', storage: [ 16, 64, 128 ] }
]