本文演示如何查找 Array Field 中 所有元素 都小于等于指定值的文档,使用 $not 结合 $gt 实现「没有任何元素大于 X」的逻辑。
创建示例数据
> db.arrayElementsNotGreaterThanDemo.insertOne({"Scores":[89,43,32,45]});
{ "acknowledged" : true, "insertedId" : ObjectId("5cd9e9f9b50a6c6dd317adb3") }
> db.arrayElementsNotGreaterThanDemo.insertOne({"Scores":[32,33,34,40]});
{ "acknowledged" : true, "insertedId" : ObjectId("5cd9ea13b50a6c6dd317adb4") }
> db.arrayElementsNotGreaterThanDemo.insertOne({"Scores":[45,56,66,69]});
{ "acknowledged" : true, "insertedId" : ObjectId("5cd9ea25b50a6c6dd317adb5") }
> db.arrayElementsNotGreaterThanDemo.insertOne({"Scores":[46,66,77,88]});
{ "acknowledged" : true, "insertedId" : ObjectId("5cd9ea3cb50a6c6dd317adb6") }
显示所有数据
> db.arrayElementsNotGreaterThanDemo.find().pretty();
{ "_id" : ObjectId("5cd9e9f9b50a6c6dd317adb3"), "Scores" : [ 89, 43, 32, 45 ] }
{ "_id" : ObjectId("5cd9ea13b50a6c6dd317adb4"), "Scores" : [ 32, 33, 34, 40 ] }
{ "_id" : ObjectId("5cd9ea25b50a6c6dd317adb5"), "Scores" : [ 45, 56, 66, 69 ] }
{ "_id" : ObjectId("5cd9ea3cb50a6c6dd317adb6"), "Scores" : [ 46, 66, 77, 88 ] }
查询:Scores 数组中所有元素都 ≤ 45(即没有元素 > 45)
> db.arrayElementsNotGreaterThanDemo.find({Scores: {$not: {$gt:45}}});
结果
{ "_id" : ObjectId("5cd9ea13b50a6c6dd317adb4"), "Scores" : [ 32, 33, 34, 40 ] }
逻辑解析
$gt: 45- 匹配「大于 45」的元素{Scores: {$gt: 45}}- 匹配「包含至少一个 >45 元素」的文档$not- 取反,变成「不包含任何 >45 元素」的文档- 等价于:所有元素都 ≤ 45
等价的替代写法
// 方法 1: $not + $gt (原文方式)
{ Scores: { $not: { $gt: 45 } } }
// 方法 2: $elemMatch + $not (语义更清晰)
{ Scores: { $not: { $elemMatch: { $gt: 45 } } } }
// 方法 3: $where (不推荐,性能差)
{ $where: "function() { return this.Scores.every(x => x <= 45); }" }
扩展:所有元素都满足条件的通用模式
// 所有元素都 > 10
{ field: { $not: { $lte: 10 } } }
// 所有元素都在 1-100 之间
{ field: { $not: { $or: [ { $lt: 1 }, { $gt: 100 } ] } } }
// 所有元素都是字符串且长度 > 3
{ field: { $not: { $elemMatch: { $or: [ { $not: { $type: "string" } }, { $strLenCP: { $lte: 3 } } ] } } }
性能提示
- 此类查询通常需要扫描整个集合(除非有特定索引支持)
- 对于大量数据,考虑在应用层验证或维护
maxScore字段 - MongoDB 3.6+ 可使用
$expr配合$allElementsTrue(但需配合 $map)
聚合管道中的等效操作
db.collection.aggregate([
{ $match: {
$expr: { $not: { $gt: [ { $max: "$Scores" }, 45 ] } }
}}
]);