find
find 方法来进行查询。查询就是返回集合中文档的一个子集,子集的范围从 0 个文档到整个集合。要返回哪些文档由 find 的第一个参数决定,该参数是一个用于指定查询条件的文档。
空的查询文档({})会匹配集合中的所有内容。如果 find 没有给定查询文档,则默认为 {}
可以在查询文档中加入多个键–值对,以将多个查询条件组合在一起,这样的查询条件会被解释为“条件 1 AND 条件 2 AND...AND 条件 N ”
db.movies.find() db.movies.find({"title": "aaa"}) db.movies.find({"title": "aaa", "age": 20})
有时候并不需要返回文档中的所有键–值对。遇到这种情况时,可以通过find(或者 findOne)的第二个参数来指定需要的键。这样做既可以节省网络传输的数据量,也可以减少客户端解码文档的时间和内存消耗。
db.movies.find({"title": "aaa", "age": 20}, {"title": 1, "age": 1}); db.movies.find({"title": "aaa", "age": 20}, {"age": 0});
查询条件
比较运算符
"$lt"、"$lte"、"$gt" 和 "$gte" 都属于比较运算符,分别对应 <、<=、> 和>=。可以将它们组合使用以查找一个范围内的值。
db.movies.find({"age": {"$gte": 18, "$lte": 30}})
OR查询
有两种方式可以进行 OR 查询。"$in" 可以用来查询一个键的多个值。"$or" 则更通用一些,可以在多个键中查询任意的给定值。
db.movies.find({"age": {"$in": [18, 20, "30"]}}) db.movies.find({"age": {"$nin": [18, 20, "30"]}}) db.movies.find({"$or": [{"age": 18}, {"age": 20}]}) db.movies.find({"$or": [{"age": {"$in": [18]}}, {"age": 20}]})
虽然总是可以使用 "$or",但只要有可能就应该使用 "$in",因为查询优化器可以更高效地对其进行处理。
$not
"$not" 是一个元条件运算符:可以用于任何其他条件之上。以取模运算符"$mod" 为例,"$mod" 会将查询的值除以第一个给定值,如果余数等于第二个给定值,则匹配成功:
db.movies.find({"_id": {"$mod": [5, 1]}}) db.movies.find({"_id": {"$not": {"$mod": [5, 1]}}})
特定类型的查询
null
null 的行为有一些特别。它可以与自身匹配
不过,null 同样会匹配“不存在”这个条件。因此,对一个键进行 null 值的请求还会返回缺少这个键的所有文档
如果仅想匹配键值为 null 的文档,则需要检查该键的值是否为 null,并且通过 "$exists" 条件确认该键已存在。
db.movies.find({"age": null}) db.movies.find({"age": {"$eq": null, "$exists": true}})
正则表达式
"$regex" 可以在查询中为字符串的模式匹配提供正则表达式功能。
db.movies.find({"title": {"$regex": /aaa/i}})
MongoDB 会使用 Perl 兼容的正则表达式(PCRE)库来对正则表达式进行匹配。任何 PCRE 支持的正则表达式语法都能被 MongoDB 接受。在查询中使用正则表达式之前,最好先在 JavaScript shell 中检查一下语法,这样可以确保匹配与预想的一致。
查询数组
db.food.insertOne({"fruit": ["apple", "banana", "peach"]}) // 查询数组元素的方式与查询标量值相同。 db.food.find({"fruit": "banana"}) db.food.insertOne({"_id": 1, "fruit": ["apple", "banana", "peach"]}) db.food.insertOne({"_id": 2, "fruit": ["apple", "kumquat", "orange"]}) db.food.insertOne({"_id": 3, "fruit": ["cherry", "banana", "apple"]}) // 如果需要通过多个元素来匹配数组,那么可以使用 "$all"。可以使用 "$all" 查询来找到同时包含元素 "apple" 和 "banana" 的文档 db.food.find({fruit: {$all: ["apple", "banana"]}}) // 也可以使用整个数组进行精确匹配。不过,精确匹配无法匹配上元素丢失或多余的文档。 db.food.find({"fruit": ["apple", "banana", "peach"]}) // 如果想在数组中查询特定位置的元素,可以使用 key.index 语法来指定下标 db.food.find({"fruit.2": "peach"}) // "$size" 条件运算符对于查询数组来说非常有用,可以用它查询特定长度的数组 db.food.find({"fruit": {"$size": 3}}) // "$slice" 运算符可以返回一个数组键中元素的子集 // 假设现在有一个关于博客文章的文档,我们希望返回前 10 条评论 db.blog.posts.findOne({}, {"comments" : {"$slice" : 10}}) // 同样,如果想返回后 10 条评论,则可以使用 -10 db.blog.posts.findOne({}, {"comments" : {"$slice" : -10}}) // "$slice" 也可以指定偏移量和返回的元素数量来获取数组中间的结果 db.blog.posts.findOne({}, {"comments" : {"$slice" : [23, 10]}}) // 如果知道数组元素的下标,那么 "$slice" 非常有用。但有时我们希望返回与查询条件匹配的任意数组元素。这时可以使用 $ 运算符来返回匹配的元素 db.blog.posts.find({"comments.name" : "bob"}, {"comments.$" : 1})
查询内嵌文档
查询内嵌文档的方法有两种:查询整个文档或针对其单个键–值对进行查询。
查询整个内嵌文档的工作方式与普通查询相同
db.movies.find({ "b2": { "name": "bbb", "rating": 4.3 } })
可以使用点表示法对内嵌文档的键进行查询:
db.movies.find({"b2.name": "bbb"})
"$elemMatch" 允许你将限定条件进行“分组”。仅当需要对一个内嵌文档的多个键进行操作时才会用到它。
db.movies.find({"b2": {"$elemMatch": {"name": "aaa", "rating": {"$gte": 2}}}})
参考: MongoDB权威指南(第3版)第 4 章 查询