MongoDB多表关联查询-$lookup---kalrry
一、聚合框架
聚合框架是MongoDB的高级查询语言,它允许我们通过转换和合并多个文档中的数据来生成新的单个文档中不存在的信息。
聚合管道操作主要包含下面几个部分:
命令 | 功能描述 | 备注 |
---|---|---|
$project | 指定输出文档里的字段 | |
$match | 选择要处理的文档,与fine()类似 | |
$limit | 限制传递给下一步的文档数量 | |
$skip | 跳过一定数量的文档 | |
$unwind | 扩展数组,为每个数组入口生成一个输出文档 | |
$group | 根据key来分组文档 | |
$sort | 排序文档 | |
$geoNear | 选择某个地理位置附近的的文档 | |
$out | 把管道的结果写入某个集合 | |
$redact | 控制特定数据的访问 | |
$lookup | 多表关联(3.2版本新增) |
以下是$lookup的使用
二、$lookup的功能及语法
-
主要功能 是将每个输入待处理的文档,经过$lookup 阶段的处理,输出的新文档中会包含一个新生成的数组列(户名可根据需要命名新key的名字 )。数组列存放的数据 是 来自 被Join 集合的适配文档,如果没有,集合为空(即 为[ ])
-
基本语法
{
$lookup:
{
from: <collection to join>,
localField: <field from the input documents>,
foreignField: <field from the documents of the "from" collection>,
as: <output array field>
}
}
- 语法的解释说明
语法值 | 功能描述 | 备注 |
---|---|---|
from | 同一个数据库下等待被Join的集合 | |
localField | 源集合中的match值,如果输入的集合中,某文档没localField这个Key(Field),在处理的过程中,会默认为此文档含有 localField:null的键值对 | |
foreignField | 待Join的集合的match值,如果待Join的集合中,文档没有foreignField | |
值,在处理的过程中,会默认为此文档含有 foreignField:null的键值对 | ||
as | 为输出文档的新增值命名。如果输入的集合中已存在该值,则会覆盖掉 |
- 注: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.insert([
{ "_id" : 1, "item" : "almonds", "price" : 12, "quantity" : 2 },
{ "_id" : 2, "item" : "pecans", "price" : 20, "quantity" : 1 },
{ "_id" : 3 }
])
- ,另一个是商品库存集合 ,存储的测试数据 如下
db.inventory.insert([
{ "_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" : NumberInt("1"),
"item" : "almonds",
"price" : NumberInt("12"),
"quantity" : NumberInt("2"),
"inventory_docs" : [
{
"_id" : NumberInt("1"),
"sku" : "almonds",
"description" : "product 1",
"instock" : NumberInt("120")
}
]
}
{
"_id" : NumberInt("2"),
"item" : "pecans",
"price" : NumberInt("20"),
"quantity" : NumberInt("1"),
"inventory_docs" : [
{
"_id" : NumberInt("4"),
"sku" : "pecans",
"description" : "product 4",
"instock" : NumberInt("70")
}
]
}
{
"_id" : NumberInt("3"),
"inventory_docs" : [
{
"_id" : NumberInt("5"),
"sku" : null,
"description" : "Incomplete"
},
{
"_id" : NumberInt("6")
}
]
}
四、参考
1、详解MongoDB