一、聚合框架

聚合框架是MongoDB的高级查询语言,它允许我们通过转换和合并多个文档中的数据来生成新的单个文档中不存在的信息。

聚合管道操作主要包含下面几个部分:

命令 功能描述 备注

$project 指定输出文档里的字段
$match 选择要处理的文档,与fine()类似
$limit 限制传递给下一步的文档数量
$skip 跳过一定数量的文档
$unwind 扩展数组,为每个数组入口生成一个输出文档
$group 根据key来分组文档
$sort 排序文档
$geoNear 选择某个地理位置附近的的文档
$out 把管道的结果写入某个集合
$redact 控制特定数据的访问
$lookup 多表关联(3.2版本新增)

以下是$lookup的使用

二、 $lookup的功能及语法

1.主要功能 是将每个输入待处理的文档,经过$lookup 阶段的处理,输出的新文档中会包含一个新生成的数组列(户名可根据需要命名新key的名字 )。数组列存放的数据 是 来自 被Join 集合的适配文档,如果没有,集合为空(即 为[ ])

2.基本语法

{
   $lookup:
     {
       from: <collection to join>,
       localField: <field from the input documents>,
       foreignField: <field from the documents of the "from" collection>,
       as: <output array field>
     }
}

3.语法的解释说明

在这里插入图片描述
4.注:null = null 此为真
其语法功能类似于下面的伪SQL语句

SELECT *, <output array field>
FROM collection
WHERE <output array field> IN (SELECT *
                               FROM <collection to join>
                               WHERE <foreignField>= <collection.localField>);

三、案例

假设 有 订单集合, 存储的测试数据 如下
其中 item 对应 数据为 商品名称

db.orders.insertMany([
{ "_id" : 1, "item" : "almonds", "price" : 12, "quantity" : 2 },
{ "_id" : 2, "item" : "pecans", "price" : 20, "quantity" : 1 }
,{ "_id" : 3  }
]);
db.inventory.insertMany([
   { "_id" : 1, "sku" : "almonds", description: "product 1", "instock" : 120 },
   { "_id" : 2, "sku" : "bread", description: "product 2", "instock" : 80 },
   { "_id" : 3, "sku" : "cashews", description: "product 3", "instock" : 60 },
   { "_id" : 4, "sku" : "pecans", description: "product 4", "instock" : 70 },
   { "_id" : 5, "sku": null, description: "Incomplete" },
   { "_id" : 6 }
]);

此集合中的 sku 数据等同于订单集合中的商品名称。
在这种模式设计下,如果要查询订单表对应商品的库存情况,应如何写代码呢?
很明显这需要两个集合Join。
接下来就是实际演示我们的关联查询的语句了:

db.orders.aggregate([
   {
     $lookup:
       {
         from: "inventory",
         localField: "item",
         foreignField: "sku",
         as: "inventory_docs"
       }
  }
])

结果:

{ "_id" : 1, "item" : "almonds", "price" : 12, "quantity" : 2, "inventory_docs" : [ { "_id" : 1, "sku" : "almonds", "description" : "product 1", "instock" : 120 } ] }
{ "_id" : 2, "item" : "pecans", "price" : 20, "quantity" : 1, "inventory_docs" : [ { "_id" : 4, "sku" : "pecans", "description" : "product 4", "instock" : 70 } ] }
{ "_id" : 3, "inventory_docs" : [ { "_id" : 5, "sku" : null, "description" : "Incomplete" }, { "_id" : 6 } ] }

那如何实现内连接呢?实际上内连接只是需要过滤空值即可。

db.orders.aggregate([
   {
     $lookup:
       {
         from: "inventory",
         localField: "item",
         foreignField: "sku",
         as: "inventory_docs"
       }
  },
  {
      $match: { "item":{$ne:null}}
   }
])

四.扩展查询

类似SQL中的on查询

由于我们查询数据的时候常常不单单是要执行联表,联表常常伴随着过滤条件,那在本案例中怎么处理呢,比如我们不要item为空的,要模糊匹配item为p的数据:

db.orders.aggregate([
    {
       $match:{item:/p/}
    },
   {
     $lookup:
       {
         from: "inventory",
         localField: "item",
         foreignField: "sku",
         as: "inventory_docs"
       }
  }
])

结果:
在这里插入图片描述

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐