MongoDB

MongoDB 知识量:13 - 42 - 129

3.2 查询条件><

查询条件- 3.2.1 -

在 MongoDB 中,查询条件用于指定 find() 方法应该返回哪些文档。查询条件是一个文档,其中包含了一组字段和值,以及可能的比较操作符。以下是一些常用的查询条件和操作符的示例:

1. 等值查询

// 查找 name 字段等于 "John" 的所有文档      
db.users.find({ name: "John" })

2. 比较查询操作符

  • $gt:大于 (greater than)

  • $gte:大于等于 (greater than or equal to)

  • $lt:小于 (less than)

  • $lte:小于等于 (less than or equal to)

  • $ne:不等于 (not equal to)

  • $in:匹配数组中的任意值

  • $nin:不匹配数组中的任意值

// 查找 age 字段大于 30 的所有文档  
db.users.find({ age: { $gt: 30 } })  
  
// 查找 age 字段大于等于 25 并且小于等于 35 的所有文档  
db.users.find({ age: { $gte: 25, $lte: 35 } })  
  
// 查找 name 字段不等于 "John" 的所有文档  
db.users.find({ name: { $ne: "John" } })  
  
// 查找 age 字段值在指定数组中的所有文档  
db.users.find({ age: { $in: [25, 30, 35] } })  
  
// 查找 age 字段值不在指定数组中的所有文档  
db.users.find({ age: { $nin: [25, 30, 35] } })

3. 逻辑查询操作符

  • $and:满足所有指定条件的文档(MongoDB 2.6 及以上版本默认提供,通常不需要显式使用)

  • $or:满足任意指定条件的文档

  • $not:反转查询条件的效果(通常与其他操作符结合使用)

  • $nor:既不满足第一个条件,也不满足第二个条件的文档

// 查找 age 大于等于 25 并且 type 等于 "admin" 的所有文档  
db.users.find({ $and: [{ age: { $gte: 25 } }, { type: "admin" }] })  
// 注意:上面的查询可以简化为  
db.users.find({ age: { $gte: 25 }, type: "admin" })  
  
// 查找 age 小于 25 或 type 等于 "user" 的所有文档  
db.users.find({ $or: [{ age: { $lt: 25 } }, { type: "user" }] })  
  
// 查找 name 字段不是 "John" 的所有文档  
db.users.find({ name: { $not: { $eq: "John" } } })  
// 注意:上面的查询可以简化为  
db.users.find({ name: { $ne: "John" } })  
  
// 查找既不满足 age 大于等于 25,也不满足 type 等于 "admin" 的所有文档  
db.users.find({ $nor: [{ age: { $gte: 25 } }, { type: "admin" }] })

4. 元素查询操作符

  • $exists:检查字段是否存在

  • $type:检查字段的类型

// 查找存在 age 字段的所有文档  
db.users.find({ age: { $exists: true } })  
  
// 查找 age 字段为整数类型的所有文档  
db.users.find({ age: { $type: "int" } }) // MongoDB 4.0 以下版本  
db.users.find({ age: { $type: "int32" } }) // MongoDB 4.0 及以上版本,更精确的类型

5. 正则表达式查询

// 查找 name 字段以 "J" 开头的所有文档  
db.users.find({ name: /^J/ })  
  
// 查找 name 字段包含 "ohn" 的所有文档(不区分大小写)  
db.users.find({ name: /ohn/i })

这些查询条件和操作符可以组合使用,以构建更复杂的查询。在 MongoDB 中,查询是非常灵活的,可以根据具体的需求来定制查询条件。

$where查询- 3.2.2 -

在 MongoDB 中,$where 是一个特殊的操作符,它允许在查询中执行 JavaScript 表达式,以选择符合该表达式的文档。使用 $where 可以提供更大的灵活性,但同时也牺牲了一些性能,因为 JavaScript 表达式的执行通常比 MongoDB 的内置查询操作符更慢。

以下是如何使用 $where 操作符的一些示例:

1. 基本用法

db.collection.find({ $where: "this.fieldName == 'someValue'" })

这个查询将返回集合中所有 fieldName 字段值为 'someValue' 的文档。这里的 this 指的是当前正在被检查的文档。

2. 复杂表达式

可以使用更复杂的 JavaScript 表达式,例如:

db.collection.find({  
  $where: "this.field1 == 'value1' && this.field2 > 5"  
})

这个查询将返回 field1 等于 'value1' 并且 field2 大于 5 的所有文档。

3. 注意事项

  • 性能问题:由于 $where 使用了 JavaScript 表达式,它通常不会使用 MongoDB 的索引,这可能导致查询非常慢,特别是在大型集合上。

  • 安全性:在 $where 查询中使用用户提供的输入可能是不安全的,因为它允许执行任意 JavaScript 代码。应该确保传入的 JavaScript 表达式是安全的,并且不能用于恶意目的。

  • 简洁性:尽可能使用 MongoDB 的内置查询操作符(如 $eq、$gt、$in 等),因为它们通常更简洁、更易于理解,并且性能更好。

由于 $where 的这些限制和潜在问题,它通常只在不能使用其他查询操作符的情况下才使用。在大多数情况下,应该能够使用 MongoDB 的标准查询操作符来满足需求。

可以传递一个函数给 $where吗?- 3.2.3 -

在 MongoDB 的官方文档中,$where 操作符的设计初衷是允许用户传递一个 JavaScript 表达式字符串,而不是一个函数。MongoDB 的查询语言不是完整的 JavaScript,它有自己的查询语法和操作符。因此,尽管从技术上来说,$where 接收的是一个字符串,这个字符串应该是一个有效的 JavaScript 表达式,但它不是直接接收 JavaScript 函数。

在 MongoDB shell 或大多数 MongoDB 驱动程序中,不能直接将一个函数传递给 $where,因为 BSON(Binary JSON,MongoDB 使用的数据交换格式)不支持函数类型。这意味着不能像下面这样做:

// 这在 MongoDB shell 或驱动程序中不会工作  
db.collection.find({  
  $where: function() {  
    return this.someField === 'someValue';  
  }  
});

相反,应该传递一个 JavaScript 表达式的字符串,如下所示:

// 这是正确的用法  
db.collection.find({  
  $where: "this.someField === 'someValue'"  
});

在这个例子中,$where 接收的字符串 "this.someField === 'someValue'" 是一个有效的 JavaScript 表达式,它将在 MongoDB 服务器端对每个文档进行求值。这里的 this 关键字引用的是当前正在检查的文档。

null值的查询- 3.2.4 -

在 MongoDB 中,如果想要查询一个字段的值为 null,不能直接使用 field: null 这样的查询条件,因为 MongoDB 会将这样的查询解释为查找不存在该字段的文档。为了准确地查询字段值为 null 的文档,需要使用 $exists 操作符或者特殊的处理方式。

然而,从 MongoDB 3.2 版本开始,可以使用 { field: { $type: 10 } } 来查询字段值为 null 的文档,因为在 MongoDB 中,null 被视为一种特殊的类型(BSON type Null,对应数字 10)。

以下是如何查询字段值为 null 的文档的示例:

// 查找 field 字段值为 null 的所有文档(适用于 MongoDB 3.2 及以上版本)  
db.collection.find({ field: { $type: 10 } })

如果还需要确保字段确实存在而不是仅仅不存在值,可以结合 $exists 操作符:

// 查找 field 字段存在且值为 null 的所有文档(正确方式)  
db.collection.find({  
  $and: [  
    { field: { $in: [null] } },  
    { field: { $exists: true } }  
  ]  
})