英文原文地址:https://docs.mongodb.com/v3.2/tutorial/query-documents/。
本文章属个人翻译,作个人学习之用,如有雷同,纯属巧合。如有错误之处,欢迎指正。
查询文档
查询方法
MongoDB提供了
db.collection.find()
方法来从集合中读取文档。
db.collection.find()
方法返回所匹配文档的
游标
。
db.collection.find(<query filter>, <projection>)
你可以指定以下可选字段:
- 查询过滤器,指定返回的文档
- 投影,指定从匹配的文档返回哪些字段。投影限制了MongoDB通过网络返回给客户端的数据量大小。
你可以选择性地添加一个游标修饰符来强制性地限制返回条数(limit)、跳过集合个数(skip),以及排序(sort)。除非你指定
sort()
,否则返回文档的顺序是不确定的。
示例集合
本文的例子在
mongo
shell中使用
db.collection.find()
方法。在
mongo
shell中,如果返回的游标没有用var关键字赋值给变量,则游标自动迭代至20次,打印结果的前20个文档。
为填充本例子中所提到的
users
集合,请在
mongo
shell中运行一下代码:
注意
如果
集合已经包含了相同_id的集合,插入文档前需要删除该集合(
users
)
db.users.drop()
db.users.insertMany( [ { _id: 1, name: "sue", age: 19, type: 1, status: "P", favorites: { artist: "Picasso", food: "pizza" }, finished: [ 17, 3 ], badges: [ "blue", "black" ], points: [ { points: 85, bonus: 20 }, { points: 85, bonus: 10 } ] }, { _id: 2, name: "bob", age: 42, type: 1, status: "A", favorites: { artist: "Miro", food: "meringue" }, finished: [ 11, 25 ], badges: [ "green" ], points: [ { points: 85, bonus: 20 }, { points: 64, bonus: 12 } ] }, { _id: 3, name: "ahn", age: 22, type: 2, status: "A", favorites: { artist: "Cassatt", food: "cake" }, finished: [ 6 ], badges: [ "blue", "red" ], points: [ { points: 81, bonus: 8 }, { points: 55, bonus: 20 } ] }, { _id: 4, name: "xi", age: 34, type: 2, status: "D", favorites: { artist: "Chagall", food: "chocolate" }, finished: [ 5, 11 ], badges: [ "red", "black" ], points: [ { points: 53, bonus: 15 }, { points: 51, bonus: 15 } ] }, { _id: 5, name: "xyz", age: 23, type: 2, status: "D", favorites: { artist: "Noguchi", food: "nougat" }, finished: [ 14, 6 ], badges: [ "orange" ], points: [ { points: 71, bonus: 20 } ] }, { _id: 6, name: "abc", age: 43, type: 1, status: "A", favorites: { food: "pizza", artist: "Picasso" }, finished: [ 18, 12 ], badges: [ "black", "blue" ], points: [ { points: 78, bonus: 8 }, { points: 57, bonus: 7 } ] } ] )
查询集合中的所有文档
一个空的
查询过滤文档
(
{}
)选中集合中的所有文档:
db.users.find( {} )
db.collection.find()
中省略查询过滤文档等价于指定一个空的查询文档。这样的话,以下操作等价于前面的操作:
db.users.find()
指定查询过滤条件
指定等于条件
查询过滤文档
可以用
<filed>:<value>
表达式指定等于条件,选择所有包含字段,且其值等于
<value>
的文档
{ <field1>: <value1>, ...}
以下例子从
users
集合中返回值字段status值为”A”的所有文档:
db.users.find( {status: "A"} )
用查询运算符指定条件
查询过滤文档
可以用
查询运算符
来指定条件,格式如下:
{ <field>: { <operator1>: <value1>}, ...}
以下例子从
users
集合中返回status字段等于”P”或”D”的文档。
db.users.find( {status: {$in: ["P", "D"]}} )
虽然你可以用
$or
运算符来表达这个查询,在相同的字段上执行相等性检查时,用
$in
,而不是用
$or
。
欲知完整的查询运算符列表,请参考查询与投影运算符。
指定 AND 条件
一个复合查询可以在文档的多个字段中指定查询条件。逻辑操作符AND把复合查询的各部分连接起来,使得该查询能够选中集合中满足所有条件的文档。
以下例子从
users
集合中返回所有status等于”A”**与**age小于30的文档:
db.users.find( {status: "A", age: {$lt: 30}} )
指定OR条件
通过
$or
运算符,你可以用逻辑OR来连接复合查询中的各部分,使得该查询能够选中集合中满足其中至少一个条件的文档。
以下例子从
users
集合中返回所有status等于”A”**或**age小于30的文档:
db.users.find( [ $or: [{status: "A"}, {age: {$lt: 30}}] ] )
同时指定AND和OR条件
通过额外的从句,你可以为匹配文档指定精确的条件。
以下例子中,复合查询文档从集合中选择status等于”A”,并且age小于30或者type等于1的记录。
db.users.find( { status: "A", $or: [{age: {$lt: 30}}, {type: 1}] } )
在嵌入文档中查询
当字段包含一个嵌入文档时,查询可以在嵌入文档上指定一个精确匹配,也可以用
点标记法
在嵌入文档上通过单独的字段来指定匹配。
精确匹配嵌入文档
要在整个嵌入文档中指定精确匹配,使用 {
<field>
:
<value>
},其中,
<value>
是匹配的文档。在嵌入文档中做相等匹配,指定的
<value>
必须精确匹配文档,包括字段顺序。
在以下例子中,该查询匹配所有的文档:favorites字段是一个只包含artist字段,其值等于”Picasso”,和food字段,其值等于”pizza”的嵌入文档,按照 artist、food的顺序:
db.users.find( {favorites: {artists: "Picasso", food: "pizza"}} )
相等匹配嵌入文档的字段
可以用
点标记法
来匹配嵌入文档中的指定字段。嵌入文档内指定字段的相等性匹配会选中包含具有指定的值的指定字段的嵌入文档,嵌入文档可以包含其他字段。
以下例子中,该查询使用
点标记法
来匹配favorites字段是一个包含值等于”Picasso”的artist字段,可能还可以包含其他字段的嵌入文档的所有文档。
db.users.find( {"favorites.artist": "Picasso"} )
在数组上的查询
当字段的值是一个数组时,你可以指定匹配整个数组,或者数组中的指定值。如果数组包含嵌入文档,你可以使用
点标记法
查询嵌入文档中的指定字段。
如果你使用
$elemMatch
操作符指定多个条件,该数组必须至少包含一个满足所有条件的元素。见 单个元素满足条件。
如果你不用
$elemMatch
指定多个条件,则数组元素的某个组合必须满足所有条件,单个元素不一定都需要满足,即,不同的数组元素可以满足条件的不同部分。见 元素的组合满足条件。
精确匹配整个数组
要指定数组的相等匹配,用查询文档
{ <field>: <value> }
,其中
<value>
是要匹配的数组。精确匹配一个数组需要满足:数组必须精确匹配指定的
<value>
,包括元素顺序。
以下例子查询badges字段是一个按顺序包含”blue”和”black”两个元素的数组的文档:
db.users.find( {badges: ["blue", "black"]} )
该查询返回以下文档:
{ "_id" : 1, "name" : "sue", "age" : 19, "type" : 1, "status" : "P", "favorites" : { "artist" : "Picasso", "food" : "pizza" }, "finished" : [ 17, 3 ] "badges" : [ "blue", "black" ], "points" : [ { "points" : 85, "bonus" : 20 }, { "points" : 85, "bonus" : 10 } ] }
匹配数组的一个元素
相等性匹配也可以指定匹配数组中的单个元素。只要数组中至少一个元素的值等于指定的值就行。
以下例子查询badges字段是一个包含”black”元素的数组的文档。
db.users.find( { badges: "black" } )
该查询返回以下文档:
{ "_id" : 1, "name" : "sue", "age" : 19, "type" : 1, "status" : "P", "favorites" : { "artist" : "Picasso", "food" : "pizza" }, "finished" : [ 17, 3 ] "badges" : [ "blue", "black" ], "points" : [ { "points" : 85, "bonus" : 20 }, { "points" : 85, "bonus" : 10 } ] } { "_id" : 4, "name" : "xi", "age" : 34, "type" : 2, "status" : "D", "favorites" : { "artist" : "Chagall", "food" : "chocolate" }, "finished" : [ 5, 11 ], "badges" : [ "red", "black" ], "points" : [ { "points" : 53, "bonus" : 15 }, { "points" : 51, "bonus" : 15 } ] } { "_id" : 6, "name" : "abc", "age" : 43, "type" : 1, "status" : "A", "favorites" : { "food" : "pizza", "artist" : "Picasso" }, "finished" : [ 18, 12 ], "badges" : [ "black", "blue" ], "points" : [ { "points" : 78, "bonus" : 8 }, { "points" : 57, "bonus" : 7 } ] }
匹配数组中的指定元素
相等性匹配也可以用
点标记法
指定匹配数组中特定下标或位置的元素。
以下例子中,该查询使用
点标记法
匹配badges字段是一个”black”作为第一个元素的数组的文档。
db.users.find( { "badges.0": "black" } )
该操作返回以下结果:
{ "_id" : 6, "name" : "abc", "age" : 43, "type" : 1, "status" : "A", "favorites" : { "food" : "pizza", "artist" : "Picasso" }, "finished" : [ 18, 12 ], "badges" : [ "black", "blue" ], "points" : [ { "points" : 78, "bonus" : 8 }, { "points" : 57, "bonus" : 7 } ] }
给数组元素指定多个条件
单个元素满足条件
使用
$elemMatch
操作符来在数组元素上指定多个条件,至少一个数组元素满足所有条件即可。
以下例子查询字段finished是一个至少一个元素大于15且小于20的数组的文档。
db.users.find( { finished: { $elemMatch: { $gt: 15, $lt: 20 } } } )
该操作返回以下文档,其finished字段是一个数组,至少一个元素满足条件。
{ "_id" : 1, "name" : "sue", "age" : 19, "type" : 1, "status" : "P", "favorites" : { "artist" : "Picasso", "food" : "pizza" }, "finished" : [ 17, 3 ] "badges" : [ "blue", "black" ], "points" : [ { "points" : 85, "bonus" : 20 }, { "points" : 85, "bonus" : 10 } ] } { "_id" : 6, "name" : "abc", "age" : 43, "type" : 1, "status" : "A", "favorites" : { "food" : "pizza", "artist" : "Picasso" }, "finished" : [ 18, 12 ], "badges" : [ "black", "blue" ], "points" : [ { "points" : 78, "bonus" : 8 }, { "points" : 57, "bonus" : 7 } ] }
数组元素的组合满足条件
以下例子查询这样的文档:其finished是一个数组,并且这个数组包含的元素的组合满足查询条件。即,一个元素满足大于15这个条件,而另外一个元素满足小于20这个条件,或者单个元素就满足这两个条件。
db.users.find( { finished: { $gt: 15, $lt: 20 } } )
该操作返回以下结果:
{ "_id" : 1, "name" : "sue", "age" : 19, "type" : 1, "status" : "P", "favorites" : { "artist" : "Picasso", "food" : "pizza" }, "finished" : [ 17, 3 ] "badges" : [ "blue", "black" ], "points" : [ { "points" : 85, "bonus" : 20 }, { "points" : 85, "bonus" : 10 } ] } { "_id" : 2, "name" : "bob", "age" : 42, "type" : 1, "status" : "A", "favorites" : { "artist" : "Miro", "food" : "meringue" }, "finished" : [ 11, 20 ], "badges" : [ "green" ], "points" : [ { "points" : 85, "bonus" : 20 }, { "points" : 64, "bonus" : 12 } ] } { "_id" : 6, "name" : "abc", "age" : 43, "type" : 1, "status" : "A", "favorites" : { "food" : "pizza", "artist" : "Picasso" }, "finished" : [ 18, 12 ], "badges" : [ "black", "blue" ], "points" : [ { "points" : 78, "bonus" : 8 }, { "points" : 57, "bonus" : 7 } ] }
嵌入文档组成的数组
用数组下标匹配嵌入文档中的字段
如果你知道嵌入文档在数组中的下标,你可以用
点标记法
来指明嵌入文档的位置。
以下例子选择这样的文档:其points字段是一个数组,数组的第一个元素是一个文档,该文档包含points字段,其值小于或等于55。
db.users.find( { 'points.0.points': { $lte: 55 } } )
该操作返回以下文档:
{ "_id" : 4, "name" : "xi", "age" : 34, "type" : 2, "status" : "D", "favorites" : { "artist" : "Chagall", "food" : "chocolate" }, "finished" : [ 5, 11 ], "badges" : [ "red", "black" ], "points" : [ { "points" : 53, "bonus" : 15 }, { "points" : 51, "bonus" : 15 } ] }
不指定数组下标来匹配字段
如果你不知道数组中文档的下标,你可以用”.”把这个数组的字段名和嵌入文档中的字段名连起来。
以下例子查询这样的文档:其points是一个数组,这个数组中的至少一个嵌入文档包含points字段,这个字段的值小于或等于55:
db.users.find( { 'points.points': { $lte: 55 } } )
该操作返回以下结果:
{ "_id" : 3, "name" : "ahn", "age" : 22, "type" : 2, "status" : "A", "favorites" : { "artist" : "Cassatt", "food" : "cake" }, "finished" : [ 6 ], "badges" : [ "blue", "red" ], "points" : [ { "points" : 81, "bonus" : 8 }, { "points" : 55, "bonus" : 20 } ] } { "_id" : 4, "name" : "xi", "age" : 34, "type" : 2, "status" : "D", "favorites" : { "artist" : "Chagall", "food" : "chocolate" }, "finished" : [ 5, 11 ], "badges" : [ "red", "black" ], "points" : [ { "points" : 53, "bonus" : 15 }, { "points" : 51, "bonus" : 15 } ] }
给文档数组指定多个条件
单个元素满足条件
用
$elemMatch
运算符,在嵌入文档组成的数组上指定多个条件,筛选出数组中至少一个嵌入文档满足所有指定条件的的文档。
以下例子查询这样的文档:其points字段是一个数组,数组中至少一个嵌入文档包含值小于或等于70的points字段,和值等于20的bonus字段。
db.users.find( { points: { $elemMatch: { points: { $lte: 70 }, bonus: 20 } } } )
该操作返回以下文档:
{ "_id" : 3, "name" : "ahn", "age" : 22, "type" : 2, "status" : "A", "favorites" : { "artist" : "Cassatt", "food" : "cake" }, "finished" : [ 6 ], "badges" : [ "blue", "red" ], "points" : [ { "points" : 81, "bonus" : 8 }, { "points" : 55, "bonus" : 20 } ] }
嵌入文档元素的组合满足条件
以下例子查询这样的文档:其points字段是一个数组,数组元素的某个组合满足查询条件,即,一个元素的points字段小于或等于70,另一个元素的bonus字段等于20,或者单个元素就满足这两个条件。
db.users.find( { "points.points": { $lte: 70 }, "points.bonus": 20 } )
该查询返回以下文档:
{ "_id" : 2, "name" : "bob", "age" : 42, "type" : 1, "status" : "A", "favorites" : { "artist" : "Miro", "food" : "meringue" }, "finished" : [ 11, 20 ], "badges" : [ "green" ], "points" : [ { "points" : 85, "bonus" : 20 }, { "points" : 64, "bonus" : 12 } ] } { "_id" : 3, "name" : "ahn", "age" : 22, "type" : 2, "status" : "A", "favorites" : { "artist" : "Cassatt", "food" : "cake" }, "finished" : [ 6 ], "badges" : [ "blue", "red" ], "points" : [ { "points" : 81, "bonus" : 8 }, { "points" : 55, "bonus" : 20 } ] }