技术干货| 一文读懂如何查询 MongoDB 文档
一.查询文档
本段提供了使用 mongo shell中 db.collection.find() 方法查询的案例。案例中使用的 inventory 集合数据可以通过下面的语句产生。
db.inventory.insertMany([
{ item: "journal", qty: 25, size: { h: 14, w: 21, uom: "cm" }, status: "A" },
{ item: "notebook", qty: 50, size: { h: 8.5, w: 11, uom: "in" }, status: "A" },
{ item: "paper", qty: 100, size: { h: 8.5, w: 11, uom: "in" }, status: "D" },
{ item: "planner", qty: 75, size: { h: 22.85, w: 30, uom: "cm" }, status: "D" },
{ item: "postcard", qty: 45, size: { h: 10, w: 15.25, uom: "cm" }, status: "A" }]);
1.1 检索集合中的所有文档
如果想检索集合中的所有文档,可以在 find 方法中传一个空文档作为查询过滤条件。查询过滤参数确定选择条件:
db.inventory.find( {} )
上述操作对应如下 SQL 语句:
SELECT * FROM inventory
有关该方法语法的更多信息,请参阅 find() 。
1.2 等值查询
在查询过滤文档中使用 <字段>:<值> 表达式实现等值查询:
{ <field1>: <value1>, ... }
下面的案例返回 inventory 集合中 status 等于 " D "** 的所有文档:
db.inventory.find( { status: "D" } )
上述操作对应如下 SQL 语句:
SELECT * FROM inventory WHERE status = "D"
1.3 查询条件中使用的操作符
查询过滤文档中可以使用查询操作符来指定多个条件,格式如下:
{ <field1>: { <operator1>: <value1> }, ... }
下面的案例返回 inventory 集合中 status 等于 " A " 或 " D " 的所有文档。
db.inventory.find( { status: { $in: [ "A", "D" ] } } )
Note:
上述操作对应如下 SQL :
SELECT * FROM inventory WHERE status in ("A", "D")
有关 MongoDB 查询运算符的完整列表,请参考查询和映射操作符。
1.4 AND 条件
可以指定文档中的多个字段作为查询条件。在查询语句中使用 AND 连接多个查询条件来检索集合中满足所有查询条件的文档。
下面的案例返回 inventory 集合中 status 等于 " A " 并且 qty小于($lt)30 的所有文档:
db.inventory.find( { status: "A", qty: { $lt: 30 } } )
上述操作对应如下 SQL :
SELECT * FROM inventory WHERE status = "A" AND qty < 30
关于 MongoDB 的比较操作符可以参考比较操作符。
1.5 OR 条件
使用 $or 运算符,可以指定一个联合查询,该查询将每个子句与逻辑 OR 连接起来,以便查询选择集合中至少匹配一个条件的文档。
下面的案例返回 inventory 集合中 status 等于 "A" 或者 qty小于 ($lt)30 的所有文档。
db.inventory.find( { $or: [ { status: "A" }, { qty: { $lt: 30 } } ] } )
上述操作对应如下 SQL :
SELECT * FROM inventory WHERE status = "A" OR qty < 30
Note:
使用比较操作符的查询受 Type Bracketing 的约束。
1.6 同时使用 AND 和 OR 条件
下面的案例返回 inventory 集合中 status 等于 "A" 并且 qty 小于 ($lt) 30 或者 item 是以 p 字符开头的所有文档。
db.inventory.find( { status: "A", $or: [ { qty: { $lt: 30 } }, { item: /^p/ } ]} )
上述操作对应如下 SQL :
SELECT * FROM inventory WHERE status = "A" AND ( qty < 30 OR item LIKE "p%")
Note:
MongoDB 支持正则表达式操作符 $regex 来做字符串模式匹配
1.7 行为
游标
使用 db.collection.find() 方法返回检索到文档的一个游标。
读隔离
新增加于 MongoDB 3.2版本。
对于副本集或者分片副本集的查询,读关注允许客户端选择读的隔离级别。更多的信息可以查看 Read Concern。
其它的方法
下面的方法也可以从集合中查询文档:
- db.collection.findOne
- 在聚合管道中,$match 管道阶段提供了 MongoDB 的查询过滤。
Note:
db.collection.findOne 方法提供了返回单个文档的读操作。
实际上,db.collection.findOne 就是 db.collection.find() 方法后面加了个限制条数1。
二.查询嵌套文档
本段提供了使用 mongo shell 中 db.collection.find() 方法查询嵌套文档的操作案例。案例中使用的 inventory 集合数据可以通过下面的语句产生。
db.inventory.insertMany( [
{ item: "journal", qty: 25, size: { h: 14, w: 21, uom: "cm" }, status: "A" },
{ item: "notebook", qty: 50, size: { h: 8.5, w: 11, uom: "in" }, status: "A" },
{ item: "paper", qty: 100, size: { h: 8.5, w: 11, uom: "in" }, status: "D" },
{ item: "planner", qty: 75, size: { h: 22.85, w: 30, uom: "cm" }, status: "D" },
{ item: "postcard", qty: 45, size: { h: 10, w: 15.25, uom: "cm" }, status: "A" }]);
对嵌套文档的字段做等值查询的时候,使用query filter document {:} 其中 **** 是等值匹配的文档。
下面的案例返回 inventory 集合中 size 字段的值等于 ** 文档 { h: 14, w: 21, uom: "cm" }** 的所有文档。
db.inventory.find( { size: { h: 14, w: 21, uom: "cm" } } )
对嵌套文档整体做等值匹配的时候,要求的是对指定 **** 文档的精确匹配,包含字段顺序。
下面的案例无法查询到任何文档。
db.inventory.find( { size: { w: 21, h: 14, uom: "cm" } } )
查询嵌套文档中的字段,使用 dot notation("field.nestedField").
Note:
当在查询语句中使用".",字段和嵌套文档字段必须在引号内。
2.1嵌套文档中的字段等值查询
下面的案例返回 inventory 集合中 size 字段中嵌套文档字段 uom 值等于 "in" 的所有文档。
db.inventory.find( { "size.uom": "in" } )
2.2 使用查询操作符查询
在 query filter document 中可以使用查询操作符指定多个查询条件,格式如下:
{ <field1>: { <operator1>: <value1> }, ... }
下面的查询语句在字段 size 中的嵌套文档字段 h 上面使用 ($lt) 操作符:
db.inventory.find( { "size.h": { $lt: 15 } } )
2.3 使用 AND 条件
下面的案例返回 inventory 集合中 size 字段中嵌套文档字段 h 值小于15 并且 size 字段中嵌套文档字段 uom 值等于 "in" 并且 status 字段等于 "D" 的所有文档。
db.inventory.find( { "size.h": { $lt: 15 }, "size.uom": "in", status: "D" } )
三.查询数组
本段提供了使用 mongo shell 中 db.collection.find() 方法查询数组的操作案例。案例中使用的 inventory 集合数据可以通过下面的语句产生。
db.inventory.insertMany([
{ item: "journal", qty: 25, tags: ["blank", "red"], dim_cm: [ 14, 21 ] },
{ item: "notebook", qty: 50, tags: ["red", "blank"], dim_cm: [ 14, 21 ] },
{ item: "paper", qty: 100, tags: ["red", "blank", "plain"], dim_cm: [ 14, 21 ] },
{ item: "planner", qty: 75, tags: ["blank", "red"], dim_cm: [ 22.85, 30 ] },
{ item: "postcard", qty: 45, tags: ["blue"], dim_cm: [ 10, 15.25 ] }]);
数组字段做等值查询的时候,使用查询文档 {:} 其中 **** 是要精确匹配的数组,包含元素的顺序。
下面的案例返回 inventory 集合中数组字段 tags 值是只包含两个元素 "red","blank" 并且有指定顺序的数组的所有文档:
db.inventory.find( { tags: ["red", "blank"] } )
如果想检索数组中包含 "red" **, "blank"** 两个元素并且不在乎元素顺序或者数组中是否有其它元素。可以使用 $all 操作符:
db.inventory.find( { tags: { $all: ["red", "blank"] } } )
3.1 查询数组中的元素
检索数组字段中至少一个元素等于指定的值,使用 : **的形式,其中 ** 是一个元素值。
下面的案例返回 inventory 集合中数组字段 tags 中有一个元素的值是 "red" 的所有文档:
db.inventory.find( { tags: "red" } )
对数组中的元素进行检索的时候,可以使用查询操作符在查询过滤文档中。
{ <array field>: { <operator1>: <value1>, ... } }
下面的案例返回 inventory 集合中数组字段 dim_cm 中最少有一个元素的值大于25的所有文档。
db.inventory.find( { dim_cm: { $gt: 25 } } )
3.2 多条件查询数组中的元素
使用多条件查询数组中的元素时,可以在查询语句中指定单个数组元素满足所有查询条件还是多个数组中的元素联合满足所有条件。
3.3 使用多条件查询数组中的元素
下面的案例返回inventory集合中数组字段dim_cm中单个元素同时满足大于15并且小于20,或者一个元素满足大于15,另外一个元素小于20的所有文档:
db.inventory.find( { dim_cm: { $gt: 15, $lt: 20 } } )
3.4 数组中的元素同时满足多个查询条件
使用 $elemMatch 来指定多个查询条件在数组中的元素上,数组中最少一个元素同时满足所有的查询条件。
下面的案例返回数组字段 dim_cm 中最少一个元素同时满足大于 ($gt)22 并且 小于 ($lt) 30 :
db.inventory.find( { dim_cm: { $elemMatch: { $gt: 22, $lt: 30 } } } )
3.5 使用数组下标查询数组中的元素
使用点号,可以为数组中指定下标的元素指定查询条件,数组下标从0开始。
Note:
当使用点号的时候,字段和嵌套文档字段必须在引号内
下面的案例返回数组字段 dim_cm 中第二个元素大于25的所有文档:
db.inventory.find( { "dim_cm.1": { $gt: 25 } } )
3.6 使用数组长度来检索
使用 $size 操作符通过数组中的元素个数来进行检索。下面的查询返回数组字段 tags 中有三个元素的所有文档 :
db.inventory.find( { "tags": { $size: 3 } } )
四.查询数组中的嵌套文档
本段提供了使用 mongo shell 中的 db.collection.find() 方法对数组中嵌套文档进行查询操作的示例。可以通过下面的语句生成本文使用的 inventory 集合。
db.inventory.insertMany( [
{ item: "journal", instock: [ { warehouse: "A", qty: 5 }, { warehouse: "C", qty: 15 } ] },
{ item: "notebook", instock: [ { warehouse: "C", qty: 5 } ] },
{ item: "paper", instock: [ { warehouse: "A", qty: 60 }, { warehouse: "B", qty: 15 } ] },
{ item: "planner", instock: [ { warehouse: "A", qty: 40 }, { warehouse: "B", qty: 5 } ] },
{ item: "postcard", instock: [ { warehouse: "B", qty: 15 }, { warehouse: "C", qty: 35 } ] }]);
4.1 查询数组中的嵌套文档
下面的案例返回 instock 数组中元素等于指定文档的的所有文档:
db.inventory.find( { "instock": { warehouse: "A", qty: 5 } } )
当对整个嵌套文档使用等值匹配的时候是要求精确匹配指定文档,包括字段顺序。比如,下面的语句并没有查询到 inventory 集合中的任何文档:
db.inventory.find( { "instock": { qty: 5, warehouse: "A" } } )
4.2 指定查询条件在数组嵌套文档的字段上
指定查询条件在数组中嵌套文档的字段上
如果你不知道数组中嵌套文档的下标,使用 (.) 号连接数组字段的名字和数组中嵌套文档中字段的名字。
下面的案例返回 instock 数组中最少有一个嵌套文档包含字段 qty 的值小于等于20的所有文档 :
db.inventory.find( { 'instock.qty': { $lte: 20 } } )
使用数组下标查询数组中嵌套文档中的字段
使用 dot notation ,可以指定查询条件在数组中指定数组下标的嵌套文档的字段上面。数组下标从0开始。
Note:
当查询使用点号的时候,字段和索引必须在引号内。
下面案例返回 instock 数组中的第一个元素是包含字段 qty 小于等于20的文档的所有文档:
db.inventory.find( { 'instock.0.qty': { $lte: 20 } } )
4.3 指定多个条件检索数组嵌套文档
当对数组中嵌套文档中多个字段指定查询条件的时候,可以在查询语句中指定单个文档满足这些查询条件或者是数组中多个文档联合(单个文档)满足这些查询条件。
单个嵌套文档中的字段满足多个查询条件
使用 $elemMatch 操作符为数组中的嵌套文档指定多个查询条件,最少一个嵌套文档同时满足所有的查询条件。
下面的案例返回 instock 数组中最少有一个嵌套文档包含 qty 等于5同时 warhouse 等于 A 的所有文档:
db.inventory.find( { "instock": { $elemMatch: { qty: 5, warehouse: "A" } } } )
下面的案例返回instock数组中最少一个嵌套文档包含字段qty大于10并且小于20的所有文档:
db.inventory.find( { "instock": { $elemMatch: { qty: { $gt: 10, $lte: 20 } } } } )
多个元素联合满足查询条件
如果数组字段上的联合查询条件没有使用 $elemMatch 运算符,查询返回数组字段中多个元素联合满足所有的查询条件的所有文档。
下面的案例返回数组字段 instock 中嵌套文档中 qty 字段大于10并且数组中其它嵌套文档(不一定是同一个嵌套文档) qty 字段小于等于20的所有文档:
db.iventory.find( { "instock.qty": { $gt: 10, $lte: 20 } } )
下面的案例返回数组字段 instock 中最少一个嵌套文档包含 qty 等于5并且最少一个嵌套文档(不一定是同一个嵌套文档)包含 warehouse 字段等于 A 的所有文档:
db.inventory.find( { "instock.qty": 5, "instock.warehouse": "A" } )
五.查询返回的字段
默认情况下,MongoDB 的查询语句返回匹配到文档的所有字段,为了限制 MongoDB 返回给应用的数据,可以通过 projection 文档来指定或限制返回的字段。
本段提供了使用 mongo shell 中 db.collection.find() 方法映射查询的案例。案例中使用的 inventory 集合数据可以通过下面的语句产生。
db.inventory.insertMany( [
{ item: "journal", status: "A", size: { h: 14, w: 21, uom: "cm" }, instock: [ { warehouse: "A", qty: 5 } ] },
{ item: "notebook", status: "A", size: { h: 8.5, w: 11, uom: "in" }, instock: [ { warehouse: "C", qty: 5 } ] },
{ item: "paper", status: "D", size: { h: 8.5, w: 11, uom: "in" }, instock: [ { warehouse: "A", qty: 60 } ] },
{ item: "planner", status: "D", size: { h: 22.85, w: 30, uom: "cm" }, instock: [ { warehouse: "A", qty: 40 } ] },
{ item: "postcard", status: "A", size: { h: 10, w: 15.25, uom: "cm" }, instock: [ { warehouse: "B", qty: 15 }, { warehouse: "C", qty: 35 } ] }]);
5.1 返回匹配文档中的所有字段
如果没有特别指定 projection , db.collection.find() 方法将会返回匹配文档的所有字段。
下面的案例返回 inventory 集合中 status 等于 "A" 的文档的所有字段。
db.inventory.find( { status: "A" } )
上述操作等价于下面的标准 SQL :
SELECT * from inventory WHERE status = "A"
5.2仅返回指定字段和_id字段
映射会返回在映射文档中显示设置为1的字段。下面的案例返回所有检索到文档中 item, status, _id 三个字段。
db.inventory.find( { status: "A" }, { item: 1, status: 1 } )
上述操作等价于下面的标准 SQL:
SELECT _id, item, status from inventory WHERE status = "A"
5.3 去除 _id 字段
可以通过在映射文档中将 _id **字段设置为 0** 来从结果集中去除 _id 字段,就像下面的例子:
db.inventory.find( { status: "A" }, { item: 1, status: 1, _id: 0 } )
上述操作等价于下面的标准 SQL :
SELECT item, status from inventory WHERE status = "A"
Note:
除_id字段外,不能在映射文档中同时使用包含和去除语句。
5.4 去除指定字段
可以使用映射来排除特定字段,而不是在匹配文档中列出要返回的字段。下面的案例返回匹配文档中除 status 和 instock 字段之外的所有字段:
db.inventory.find( { status: "A" }, { status: 0, instock: 0 } )
Note:
除_id字段外,不能在映射文档中同时使用包含和去除语句。
5.5 返回嵌套文档中的指定字段
通过点号引用嵌套文档字段并且在映射文档中将该字段设置为1来实现返回嵌套文档中的指定字段。
下面的案例返回:
- _id字段(默认返回)
- item字段
- status字段
- 文档size中的uom字段
uom 字段是 size 嵌套文档中的字段.
db.inventory.find( { status: "A" },
{ item: 1, status: 1, "size.uom": 1 })
5.6 去除嵌套文档中的指定字段
通过点号引用嵌套文档字段并且在映射文档中将该字段设置为0来实现去除嵌套文档中的指定字段。下面的案例返回匹配文档中除嵌套文档 size 中的 uom 字段外的所有字段。
db.inventory.find( { status: "A" }, { "size.uom": 0 })
5.7 映射数组中的嵌套文档的指定字段
通过使用点号来映射数组中嵌套文档的指定字段。
下面案例返回:
- _id字段(默认返回)
- item字段
- status字段
- 数组字段instock中的嵌套文档中的qty字段
db.inventory.find( { status: "A" },
{ item: 1, status: 1, "instock.qty": 1 } )
5.8 映射返回数组中指定的数组元素
对于数组字段,MongoDB 提供了以下用于操作数组的映射运算符: $elemMatch , $slice , $。
下面的案例使用 $slice 映射操作符返回数组字段 instock 中最后的元素:
db.inventory.find( { status: "A" },
{ item: 1, status: 1, instock: { $slice: -1 } } )
$elemMatch , $slice , $ 是将指定元素映射到返回数组中的唯一方法。
举个例子,不能使用数组下标来映射指定的数组元素。例如: { "instock.0": 1 } 映射不会用第一个元素来映射数组。
参考:Query Documents
查询导航链接
- 查询文档
- 查询嵌套文档
- 查询数组
- 查询数组中嵌套文档
- 查询返回的字段
关于译者:张芷嘉
MongoDB 中文社区翻译小组成员;
MongoDB 中文用户文档·CRUD 操作章节负责人;
喜欢跑步,做饭,睡觉,出门三公里就困。使用 MongoDB 多年,倍感丝滑。
文章转载自公众号:Mongoing中文社区