Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> MongoDB

MongoDB 查询:Array 所有元素都小于指定值 ($not + $gt)

本文演示如何查找 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 ] } }
  }}
]);