4

技术干货| 一文读懂如何查询 MongoDB 文档

 2 years ago
source link: https://mongoing.com/archives/82302
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

技术干货| 一文读懂如何查询 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:尽管可以使用 $or 操作符来满足上述需求,但是在对相同字段进行等值检索的时候更建议使用 $in 。

上述操作对应如下 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:

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 行为游标读隔离新增加于 MongoDB 3.2版本。对于副本集或者分片副本集的查询,读关注允许客户端选择读的隔离级别。更多的信息可以查看 Read Concern

其它的方法

下面的方法也可以从集合中查询文档:

Note:db.collection.findOne 方法提供了返回单个文档的读操作。

二.查询嵌套文档

本段提供了使用 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 使用查询操作符查询

{ <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 并且 小于 ($lt30 :

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 等于 的所有文档:

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 字段等于 的所有文档:

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 返回匹配文档中的所有字段

下面的案例返回 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 多年,倍感丝滑。社区招募

为了让社区组委会成员和志愿者朋友们灵活参与,同时我们为想要深度参与社区建设的伙伴们开设了“招募通道”,如果您想要在社区里面结交志同道合的技术伙伴,想要通过在社区沉淀有价值的干货内容,想要一个展示自己的舞台,提升自身的技术影响力,即刻加入社区贡献队伍~ 点击链接提交申请:http://mongoingmongoing.mikecrm.com/CPDCj1B社区合作

接下来我们会在诸多城市举办技术大会,如果您有优质的议题和 MongoDB 相关经验的嘉宾可以与我们分享,或者有赞助合作意向的小伙伴,包含但不限制于联合主办方、媒体合作等,都可以随时联系我们的社区助手小芒果(微信ID:mongoingcom)沟通具体事宜。重要资讯

感谢大家一直以来对社区的关注与支持!社区在大家共同的努力下不断的发展与壮大,为了给大家营造更便捷的交流环境,QQ 技术交流群将同步在“微信技术交流群”中。添加小芒果微信发送“mongo”即可进入技术交流群。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK