文档菜单
文档首页
/ / /
Node.js 驱动程序
/

多字段连接

在本页

  • 简介
  • 聚合任务摘要
  • 开始之前
  • 教程
  • 添加一个查找阶段以链接集合和导入字段
  • 添加一个匹配阶段以包含2020年订购的产品
  • 添加一个未设置阶段以删除不需要的字段
  • 运行聚合管道
  • 解释结果

在本教程中,您可以学习如何使用Node.js驱动程序构建聚合管道,在集合上执行聚合,并通过完成并运行一个示例应用程序来打印结果。

此聚合执行多字段连接。多字段连接发生在您使用的两个集合的文档中有多个对应的字段时,用于匹配文档。聚合将这些文档匹配在字段值上,并将两方面的信息合并到一个文档中。

提示

一对一连接

一对一连接是多字段连接的一种形式。当您执行一对一连接时,从匹配字段值的多份文档中选择一个字段。要了解更多关于这些数据关系的信息,请参阅维基百科条目一对一(数据模型)多对多(数据模型)。

本教程演示了如何将描述产品信息的集合数据与另一个描述客户订单的集合数据结合起来。结果展示了一个包含2020年订单详情的产品列表。

此示例使用了两个集合

  • products,其中包含描述商店销售的产品的文档

  • orders,其中包含描述商店中产品单个订单的文档

一个订单只能包含一个产品,因此聚合使用多字段连接来匹配产品文档和表示该产品订单的文档。通过在products集合中的文档中的namevariation字段与在orders集合中的文档中的product_nameproduct_variation字段相匹配,将集合连接起来。

在开始本教程之前,请完成聚合模板应用程序说明,以设置一个可工作的Node.js应用程序。

设置应用程序后,通过将以下代码添加到应用程序中,访问productsorders集合

const productsColl = aggDB.collection("products");
const ordersColl = aggDB.collection("orders");

删除任何现有数据,并按以下代码将示例数据插入到products集合中

await productsColl.deleteMany({});
const productsData = [
{
name: "Asus Laptop",
variation: "Ultra HD",
category: "ELECTRONICS",
description: "Great for watching movies",
},
{
name: "Asus Laptop",
variation: "Standard Display",
category: "ELECTRONICS",
description: "Good value laptop for students",
},
{
name: "The Day Of The Triffids",
variation: "1st Edition",
category: "BOOKS",
description: "Classic post-apocalyptic novel",
},
{
name: "The Day Of The Triffids",
variation: "2nd Edition",
category: "BOOKS",
description: "Classic post-apocalyptic novel",
},
{
name: "Morphy Richards Food Mixer",
variation: "Deluxe",
category: "KITCHENWARE",
description: "Luxury mixer turning good cakes into great",
},
];
await productsColl.insertMany(productsData);

删除任何现有数据,并按以下代码将示例数据插入到orders集合中

await ordersColl.deleteMany({});
const orderData = [
{
customer_id: "elise_smith@myemail.com",
orderdate: new Date("2020-05-30T08:35:52Z"),
product_name: "Asus Laptop",
product_variation: "Standard Display",
value: 431.43,
},
{
customer_id: "tj@wheresmyemail.com",
orderdate: new Date("2019-05-28T19:13:32Z"),
product_name: "The Day Of The Triffids",
product_variation: "2nd Edition",
value: 5.01,
},
{
customer_id: "oranieri@warmmail.com",
orderdate: new Date("2020-01-01T08:25:37Z"),
product_name: "Morphy Richards Food Mixer",
product_variation: "Deluxe",
value: 63.13,
},
{
customer_id: "jjones@tepidmail.com",
orderdate: new Date("2020-12-26T08:55:46Z"),
product_name: "Asus Laptop",
product_variation: "Standard Display",
value: 429.65,
},
];
await ordersColl.insertMany(orderData);
1

管道的第一阶段是一个$lookup阶段,用于通过每个集合中的两个字段将orders集合与products集合进行连接。查找阶段包含一个嵌入式管道来配置连接。

在嵌入式管道中,添加一个$match阶段,以匹配连接两边的两个字段的值。注意以下代码使用别名来引用在创建$lookup阶段时设置的namevariation字段。

const embedded_pl = [];
embedded_pl.push({
$match: {
$expr: {
$and: [
{ $eq: ["$product_name", "$$prdname"] },
{ $eq: ["$product_variation", "$$prdvartn"] },
],
},
},
});

在嵌入式管道中,再添加一个$match阶段,以匹配2020年下的订单。

embedded_pl.push({
$match: {
orderdate: {
$gte: new Date("2020-01-01T00:00:00Z"),
$lt: new Date("2021-01-01T00:00:00Z"),
},
},
});

在嵌入式管道中,添加一个$unset阶段,从连接的orders集合端删除不需要的字段。

embedded_pl.push({
$unset: ["_id", "product_name", "product_variation"],
});

嵌入式管道完成后,将$lookup阶段添加到主聚合管道中。配置此阶段,将处理后的查找字段存储在一个名为orders的数组字段中。

pipeline.push({
$lookup: {
from: "orders",
let: {
prdname: "$name",
prdvartn: "$variation",
},
pipeline: embedded_pl,
as: "orders",
},
});
2

接下来,添加一个$match阶段,仅显示在2020年至少有一个订单的产品,基于上一步计算的orders数组。

pipeline.push({
$match: {
orders: { $ne: [] },
},
});
3

最后,添加一个$unset阶段。$unset阶段从结果文档中删除_iddescription字段。

pipeline.push({
$unset: ["_id", "description"],
});
4

将以下代码添加到您的应用程序末尾,以对products集合进行聚合操作

const aggregationResult = await productsColl.aggregate(pipeline);

最后,在您的shell中运行以下命令以启动您的应用程序

node agg_tutorial.js
5

聚合结果包含两个文档。这些文档表示在2020年有订单的产品。每个文档都包含一个orders数组字段,列出了该产品的每个订单的详细信息

{
name: 'Asus Laptop',
variation: 'Standard Display',
category: 'ELECTRONICS',
orders: [
{
customer_id: 'elise_smith@myemail.com',
orderdate: 2020-05-30T08:35:52.000Z,
value: 431.43
},
{
customer_id: 'jjones@tepidmail.com',
orderdate: 2020-12-26T08:55:46.000Z,
value: 429.65
}
]
}
{
name: 'Morphy Richards Food Mixer',
variation: 'Deluxe',
category: 'KITCHENWARE',
orders: [
{
customer_id: 'oranieri@warmmail.com',
orderdate: 2020-01-01T08:25:37.000Z,
value: 63.13
}
]
}

结果文档包含来自orders集合和products集合的文档的详细信息,并通过产品名称和变体进行连接。

要查看本教程的完整代码,请参阅GitHub上的完成的多个字段连接应用程序

返回

一对一连接