Query Documents

此页提供了使用 mongo shell 中的 db.collection.find() 方法进行查询操作的示例。

此页上的示例使用库存集合。若要填充清单集合, 请运行以下命令:

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" }
]);

查询所有

db.inventory.find( {} )

指定相等的条件

下面的示例从库存集合中选择状态等于 “d” 的所有文档:

db.inventory.find( { status: "D" } )

指定查询条件

查询筛选器文档可以使用查询运算符以以下形式指定条件:

db.inventory.find( { status: { $in: [ "A", "D" ] } } )

注意

尽管可以使用 $or 运算符来表示此查询, 但在对同一字段执行相等性检查时, 请使用 $in 运算符, 而不是 $or 运算符。

指定 & 条件

复合查询可以为集合文档中的多个字段指定条件。

隐式地, 逻辑 and 连词连接复合查询的子句, 以便查询选择集合中与所有条件匹配的文档。

下面的示例检索清单集合中状态等于 “a” 且 qty 小于 ($lt) 30 的所有文档:

db.inventory.find( { status: "A", qty: { $lt: 30 } } )

指定 or 条件

使用 $or 运算符, 可以指定一个复合查询, 该查询用逻辑或连词连接每个子句, 以便查询选择集合中至少匹配一个条件的文档。

下面的示例检索集合中状态等于 “a” 或 qty 小于 ($lt) 30 的所有文档:

db.inventory.find( { $or: [ { status: "A" }, { qty: { $lt: 30 } } ] } )

使用 and/or

在下面的示例中, 复合查询文档选择集合中状态等于 “a” 且数量小于 ($lt) 30 或项目以字符 p 开头的集合中的所有文档:

db.inventory.find( {
     status: "A",
     $or: [ { qty: { $lt: 30 } }, { item: /^p/ } ]
} )

行为

光标

db.collection.find() 方法将光标返回到匹配的文档。

阅读隔离

3.2 版中的新版本。

对于对副本集和副本集分片的读取, 读取关注允许客户端为其读取选择隔离级别。

有关详细信息, 请参阅阅读关注。

查询嵌套结果

数据初始化

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" }
]);

匹配嵌入的/嵌套文档

若要在嵌入/嵌套文档的字段上指定相等条件, 请使用查询筛选器文档 {<field>: <value>}, 其中 <value> 是要匹配的文档。

例如, 下面的查询选择字段大小等于文档 {h:14, w:21, uom: "cm"} 的所有文档:

db.inventory.find( { size: { h: 14, w: 21, uom: "cm" } } )
  • 查询结果
{ "_id" : ObjectId("5c1644baf29beabd5b32d1ac"), "item" : "journal", "qty" : 25, "size" : { "h" : 14, "w" : 21, "uom" : "cm" }, "status" : "A" }

嵌套字段的查询

若要在嵌入嵌套文档中的字段上指定查询条件, 请使用点符号 ("field.nestedfield")

注意

使用点表示法查询时, 字段和嵌套字段必须在引号内。

db.inventory.find( { "size.uom": "in" } )

使用查询运算符指定匹配

查询筛选器文档可以使用查询运算符以以下形式指定条件:

db.inventory.find( { "size.h": { $lt: 15 } } )

使用 AND

下面的查询选择嵌套字段 h 小于15、嵌套字段 uom 等于 “in” 和状态字段等于 “d” 的所有文档:

db.inventory.find( { "size.h": { $lt: 15 }, "size.uom": "in", status: "D" } )

查询一个数组

数据初始化

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 ] }
]);

匹配一个数组

若要指定数组上的相等条件, 请使用查询文档 {<field>: <value>}, 其中 <value> 是要匹配的确切数组, 包括元素的顺序。

下面的示例按指定的顺序查询字段标记值是一个具有 “红色” 和 “空白” 这两个元素的数组的所有文档:

db.inventory.find( { tags: ["red", "blank"] } )
  • 结果
{ "_id" : ObjectId("5c1645edf29beabd5b32d1b2"), "item" : "notebook", "qty" : 50, "tags" : [ "red", "blank" ], "dim_cm" : [ 14, 21 ] }

相反, 如果您希望找到一个同时包含元素 “红色” 和 “空白” 的数组, 而不考虑数组中的顺序或其他元素, 请使用 $all 运算符:

db.inventory.find( { tags: { $all: ["red", "blank"] } } )
  • 结果
{ "_id" : ObjectId("5c1645edf29beabd5b32d1b1"), "item" : "journal", "qty" : 25, "tags" : [ "blank", "red" ], "dim_cm" : [ 14, 21 ] }
{ "_id" : ObjectId("5c1645edf29beabd5b32d1b2"), "item" : "notebook", "qty" : 50, "tags" : [ "red", "blank" ], "dim_cm" : [ 14, 21 ] }
{ "_id" : ObjectId("5c1645edf29beabd5b32d1b3"), "item" : "paper", "qty" : 100, "tags" : [ "red", "blank", "plain" ], "dim_cm" : [ 14, 21 ] }
{ "_id" : ObjectId("5c1645edf29beabd5b32d1b4"), "item" : "planner", "qty" : 75, "tags" : [ "blank", "red" ], "dim_cm" : [ 22.85, 30 ] }

查询元素的数组

若要查询数组字段是否至少包含一个具有指定值的元素, 请使用筛选器 {<field>: <value>}, 其中 <value> 是元素值。

下面的示例查询标记是包含字符串 “红色” 作为其元素之一的数组的所有文档:

db.inventory.find( { tags: "red" } )

例如, 对于数组 dim_cm 包含至少一个值大于25的元素的所有文档, 下面的操作将查询。

db.inventory.find( { dim_cm: { $gt: 25 } } )

指定数组元素的多个条件

在数组元素上指定复合条件时, 可以指定查询, 使单个数组元素满足这些条件或数组元素的任意组合满足条件。

在数组元素上查询具有复合筛选条件的阵列

下面的示例查询的文档, 其中 dim_cm 数组包含在某些组合中满足查询条件的元素;

例如, 一个元素可以满足大于15个条件, 另一个元素可以满足小于20个条件, 或者一个元素可以满足这两个条件:

db.inventory.find( { dim_cm: { $gt: 15, $lt: 20 } } )
  • 查询结果
{ "_id" : ObjectId("5c1645edf29beabd5b32d1b1"), "item" : "journal", "qty" : 25, "tags" : [ "blank", "red" ], "dim_cm" : [ 14, 21 ] }
{ "_id" : ObjectId("5c1645edf29beabd5b32d1b2"), "item" : "notebook", "qty" : 50, "tags" : [ "red", "blank" ], "dim_cm" : [ 14, 21 ] }
{ "_id" : ObjectId("5c1645edf29beabd5b32d1b3"), "item" : "paper", "qty" : 100, "tags" : [ "red", "blank", "plain" ], "dim_cm" : [ 14, 21 ] }
{ "_id" : ObjectId("5c1645edf29beabd5b32d1b5"), "item" : "postcard", "qty" : 45, "tags" : [ "blue" ], "dim_cm" : [ 10, 15.25 ] }

查询满足多个条件的数组元素

使用 $elemMatch 运算符在数组的元素上指定多个条件, 以便至少有一个数组元素满足所有指定的条件。

下面的示例查询的文档中, dim_cm 数组至少包含一个元素, 该元素既大于 ($gt) 22, 又小于 ($lt) 30:

db.inventory.find( { dim_cm: { $elemMatch: { $gt: 22, $lt: 30 } } } )
  • 结果
{ "_id" : ObjectId("5c1645edf29beabd5b32d1b4"), "item" : "planner", "qty" : 75, "tags" : [ "blank", "red" ], "dim_cm" : [ 22.85, 30 ] }

按数组索引位置查询元素

使用点表示法, 可以在数组的特定索引或位置为元素指定查询条件。

数组使用从零开始的索引。

注意

使用点表示法查询时, 字段和嵌套字段必须在引号内。

下面的示例查询数组 dim_cm 中第二个元素大于25的所有文档:

db.inventory.find( { "dim_cm.1": { $gt: 25 } } )
  • 结果
{ "_id" : ObjectId("5c1645edf29beabd5b32d1b4"), "item" : "planner", "qty" : 75, "tags" : [ "blank", "red" ], "dim_cm" : [ 22.85, 30 ] }

按数组长度查询数组

使用 $size 运算符按元素数查询数组。

例如, 下面选择数组标记具有3个元素的文档。

db.inventory.find( { "tags": { $size: 3 } } )
  • 结果
{ "_id" : ObjectId("5c1645edf29beabd5b32d1b3"), "item" : "paper", "qty" : 100, "tags" : [ "red", "blank", "plain" ], "dim_cm" : [ 14, 21 ] }

查询数组中的嵌套元素

初始化

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 } ] }
]);

顺序指定查询

  • 脚本
db.inventory.find({"instock": {warehouse: "A", qty: 5} });
  • 结果
{ "_id" : ObjectId("5c164864f29beabd5b32d1b6"), "item" : "journal", "instock" : [ { "warehouse" : "A", "qty" : 5 }, { "warehouse" : "C", "qty" : 15 } ] }

注意:上面的查询和属性字段的顺序也是有关联的。

比如下面的查询则没有匹配结果。

db.inventory.find( { "instock": { qty: 5, warehouse: "A" } } )

指定查询条件

在文档数组中嵌入的字段上指定查询条件

如果不知道嵌套在数组中的文档的索引位置, 请在嵌套文档中使用点 (.) 和字段的名称连接数组字段的名称。

下面的示例选择任何文档, 其中 instock 数组至少有一个嵌入文档, 其中包含值小于或等于20的字段 qty:

db.inventory.find( { 'instock.qty': { $lte: 20 } } )

指定数组下标

使用点表示法, 可以在数组的特定索引或位置为文档中的字段指定查询条件。数组使用从零开始的索引。

注意

使用点表示法查询时, 字段和索引必须在引号内。

下面的示例选择所有文档, 其中 instock 数组的第一个元素是包含字段 qty 的文档, 其值小于或等于 20:

db.inventory.find( { 'instock.0.qty': { $lte: 20 } } )

指定文档数组的多个条件

在文档数组中嵌套的多个字段上指定条件时, 可以指定查询, 使单个文档满足这些条件, 或者数组中的任何文档组合 (包括单个文档) 满足条件。

单个嵌套文档满足嵌套字段上的多个查询条件

使用 $elemMatch 运算符在嵌入文档数组上指定多个条件, 以便至少有一个嵌入文档满足所有指定的条件。

下面的示例查询的文档, 如果 instock 数组至少有一个嵌入文档, 其中包含既包含等于5的字段 qty, 也包含等于 A 的字段仓库:

db.inventory.find( { "instock": { $elemMatch: { qty: 5, warehouse: "A" } } } )
  • 结果
{ "_id" : ObjectId("5c164864f29beabd5b32d1b6"), "item" : "journal", "instock" : [ { "warehouse" : "A", "qty" : 5 }, { "warehouse" : "C", "qty" : 15 } ] }

下面的示例查询的文档, 如果 instock 数组至少有一个嵌入文档, 其中包含大于10且小于或等于20的字段 qty:

db.inventory.find( { "instock": { $elemMatch: { qty: { $gt: 10, $lte: 20 } } } } )
  • 结果
{ "_id" : ObjectId("5c164864f29beabd5b32d1b6"), "item" : "journal", "instock" : [ { "warehouse" : "A", "qty" : 5 }, { "warehouse" : "C", "qty" : 15 } ] }
{ "_id" : ObjectId("5c164864f29beabd5b32d1b8"), "item" : "paper", "instock" : [ { "warehouse" : "A", "qty" : 60 }, { "warehouse" : "B", "qty" : 15 } ] }
{ "_id" : ObjectId("5c164864f29beabd5b32d1ba"), "item" : "postcard", "instock" : [ { "warehouse" : "B", "qty" : 15 }, { "warehouse" : "C", "qty" : 35 } ] }

满足标准的元素组合

如果数组字段上的复合查询条件不使用 $elemMatch 运算符, 则查询将选择数组包含满足条件的任何元素组合的文档。

例如, 下面的查询匹配嵌套在 instock 数组中的任何文档的 qty 字段大于 10, 而数组中的任何文档 (但不一定是相同的嵌入文档) 的 qty 字段小于或等于20的文档:

db.inventory.find( { "instock.qty": { $gt: 10,  $lte: 20 } } )
  • 结果
{ "_id" : ObjectId("5c164864f29beabd5b32d1b6"), "item" : "journal", "instock" : [ { "warehouse" : "A", "qty" : 5 }, { "warehouse" : "C", "qty" : 15 } ] }
{ "_id" : ObjectId("5c164864f29beabd5b32d1b8"), "item" : "paper", "instock" : [ { "warehouse" : "A", "qty" : 60 }, { "warehouse" : "B", "qty" : 15 } ] }
{ "_id" : ObjectId("5c164864f29beabd5b32d1b9"), "item" : "planner", "instock" : [ { "warehouse" : "A", "qty" : 40 }, { "warehouse" : "B", "qty" : 5 } ] }
{ "_id" : ObjectId("5c164864f29beabd5b32d1ba"), "item" : "postcard", "instock" : [ { "warehouse" : "B", "qty" : 15 }, { "warehouse" : "C", "qty" : 35 } ] }

下面的示例查询的文档, 其中 instock 数组至少有一个嵌入文档, 其中包含字段 qty 等于5和至少一个嵌入文档 (但不一定是相同的嵌入文档), 其中包含等于字段仓库的字段仓库答:

db.inventory.find( { "instock.qty": 5, "instock.warehouse": "A" } )
  • 结果
{ "_id" : ObjectId("5c164864f29beabd5b32d1b6"), "item" : "journal", "instock" : [ { "warehouse" : "A", "qty" : 5 }, { "warehouse" : "C", "qty" : 15 } ] }
{ "_id" : ObjectId("5c164864f29beabd5b32d1b9"), "item" : "planner", "instock" : [ { "warehouse" : "A", "qty" : 40 }, { "warehouse" : "B", "qty" : 5 } ] }

指定查询返回的字段

默认情况下, mongodb 中的查询返回匹配文档中的所有字段。

若要限制 mongodb 发送到应用程序的数据量, 可以包括投影文档, 以指定或限制要返回的字段。

数据初始化

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 } ] }
]);

返回指定的字段和 _id 字段

至于为什么 item: 1 这种写法,个人感觉是为了符合 json 的格式,感觉为了符合 json 的格式对简洁性做了牺牲。

db.inventory.find({status: "A"}, {item: 1, status: 1})

等同于

SELECT _id, item, status from inventory WHERE status = "A"

返回指定的字段,排除 _id 字段

db.inventory.find({status: "A"}, {item: 1, status: 1, _id: 0})

等同于

SELECT item, status from inventory WHERE status = "A"

返回所有字段,除了排除的字段

db.inventory.find({status: "A"}, {item: 0, status: 0})

注意

除了 _id 字段之外, 不能在投影文档中合并包含语句和排除语句。

返回指定字段的嵌套字段

您可以返回嵌入文档中的特定字段。使用点符号引用嵌入的字段, 并在投影文档中设置为1。

下面的示例返回:

  • _id 字段 (默认返回),

  • 项目字段,

  • 状态字段,

  • 大小文档中的 uom 字段。

  • uom 字段仍嵌入到大小文档中。

db.inventory.find(
   { status: "A" },
   { item: 1, status: 1, "size.uom": 1 }
)

禁止嵌入文档中的特定字段

您可以禁止显示嵌入文档中的特定字段。

使用点符号引用投影文档中的嵌入字段, 并将其设置为0。

下面的示例指定一个 projection, 以排除大小文档中的 uom 字段。所有其他字段都将在匹配的文档中返回:

db.inventory.find(
   { status: "A" },
   { "size.uom": 0 }
)

阵列中嵌入文档的投影

使用点表示法在嵌入到数组中的文档中投影特定字段。

下面的示例指定要返回的投影:

  • _id 字段 (默认返回),

  • 项目字段,

  • 状态字段,

  • 嵌入在存储数组中的文档中的 qty 字段。

db.inventory.find( { status: "A" }, { item: 1, status: 1, "instock.qty": 1 } )

返回数组中的项目特定数组元素

对于包含数组的字段, mongodb 提供了以下用于操作数组的投影运算符: $elemMatch、$slice 和 $。

下面的示例使用 $slice 投影运算符返回存储数组中的最后一个元素:

db.inventory.find( { status: "A" }, { item: 1, status: 1, instock: { $slice: -1 } } )

$elemMatch、$slice 和 $ 是预测要包含在返回数组中的特定元素的唯一方法。

例如, 不能使用数组索引投影特定的数组元素;投影不会使用第一个元素投影数组。

查询 NULL 或者不存在的字段

mongodb 中的不同查询运算符以不同的方式处理空值。

初始化

db.inventory.insertMany([
   { _id: 1, item: null },
   { _id: 2 }
])

相等过滤

{item: null} 查询匹配包含其值为 null 或不包含项字段的项字段的文档。

db.inventory.find( { item: null } )
  • 结果
{ "_id" : 1, "item" : null }
{ "_id" : 2 }

类型检查

{item: {$type:10} 查询仅与包含其值为 null 的项字段的文档匹配;

即项字段的值为 bson 类型 null (类型 10):

db.inventory.find( { item : { $type: 10 } } )
  • 结果
{ "_id" : 1, "item" : null }

存在检查

{item: {$exists: false} 查询与不包含项字段的文档匹配:

db.inventory.find( { item : { $exists: false } } )
  • 结果
{ "_id" : 2 }

参考资料

query-embedded-documents