数据库之MongoDB高级查询篇

956 阅读1分钟

1. 嵌套查询

1.0 准备数据

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 实例

如果我们需要查询size中属性uom为指定条件的条目,这就是嵌套查询,嵌套查询有两种方式可以支持。

  • 第一种:query filter document(过滤器文档查询)
// uom:"cm"的意思就是查询umo 为 cm的条目
db.inventory.find( { size: { h: 14, w: 21, uom: "cm" } } )
  • 第二种:dot notation(点符号查询)
db.inventory.find( { "size.uom": "in" } )
//  也可以使用范围查询
db.inventory.find( { "size.h": { $lt: 15 } } )

2. 基于数组的查询

2.0 准备数据

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

2.1 实例

如果一个条目中属性的字段的类型为数组,mongo也可以有匹配的查询语法支持。具体如下:

// 精确匹配数组中的元素,如果元素是多个则顺序必须一致
db.inventory.find( { tags: ["red", "blank"] } )
// 匹配字段中是否包含有查询的元素,不考虑排序或是其他元素的情况
db.inventory.find( { tags: { $all: ["red", "blank"] } } )
// 支持范围查询
db.inventory.find( { dim_cm: { $gt: 25 } } )
// 支持多条件的查询
db.inventory.find( { dim_cm: { $gt: 15, $lt: 20 } } )
db.inventory.find( { dim_cm: { $elemMatch: { $gt: 22, $lt: 30 } } } )
// 使用下标指定具体需要比对的元素
db.inventory.find( { "dim_cm.1": { $gt: 25 } } )
// 长度比对
db.inventory.find( { "tags": { $size: 3 } } )

3. 基于数组嵌套文档对象

3.0 数据准备

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

3.1 实例

// 单一条件查询
db.inventory.find( { "instock": { warehouse: "A", qty: 5 } } )
// 范围查询
db.inventory.find( { 'instock.qty': { $lte: 20 } } )
// 下标查询
db.inventory.find( { 'instock.0.qty': { $lte: 20 } } )
// 多条件查询
db.inventory.find( { "instock": { $elemMatch: { qty: { $gt: 10, $lte: 20 } } } } )

4 查询指定属性

4.0 准备数据

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

4.1 实例

有的时候查询的字段不需要所有的字段,mongodb支持查询指定的字段,具体如下:

// 查询两个字段以及默认的_id字段
db.inventory.find( { status: "A" }, { item: 1, status: 1 } )
// 忽略_id字段
db.inventory.find( { status: "A" }, { item: 1, status: 1, _id: 0 } )
// 排除两个字段
db.inventory.find( { status: "A" }, { status: 0, instock: 0 } )
// 包含条件
db.inventory.find(
   { status: "A" },
   { item: 1, status: 1, "size.uom": 1 }
)
// 排除嵌套中的某个字段
db.inventory.find(
   { status: "A" },
   { "size.uom": 0 }
)
// 显示嵌套中的数组字段
db.inventory.find( { status: "A" }, { item: 1, status: 1, "instock.qty": 1 } )
// 显示数组字段并指定期范围
db.inventory.find( { status: "A" }, { item: 1, status: 1, instock: { $slice: -1 } } )

5. 聚合查询

5.1 实例

mongodb也支持聚合查询,对数据进行聚合分析,具体如下:

// 取字段最大的值
db.orders.aggregate([
   { $match: { status: "A" } },
   { $group: { _id: "$cust_id", total: { $sum: "$amount" } } }
])

// 复杂聚合
{ $addFields: {
    maxTime: { $max: "$times" },
    minTime: { $min: "$times" }
} },
{ $project: {
    _id: 1, name: 1, times: 1, maxTime: 1, minTime: 1,
    avgTime: { $avg: ["$maxTime", "$minTime"] }
} },

{ $match: {

    name: "Joe Schmoe",

    maxTime: { $lt: 20 },

    minTime: { $gt: 5 },

    avgTime: { $gt: 7 }

} }

{ $match: { name: "Joe Schmoe" } },

{ $addFields: {
    maxTime: { $max: "$times" },
    minTime: { $min: "$times" }
} },

{ $match: { maxTime: { $lt: 20 }, minTime: { $gt: 5 } } },

{ $project: {
    _id: 1, name: 1, times: 1, maxTime: 1, minTime: 1,
    avgTime: { $avg: ["$maxTime", "$minTime"] }
} },

{ $match: { avgTime: { $gt: 7 } } }