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

一对一连接

本页内容

  • 简介
  • 聚合任务摘要
  • 开始之前
  • 教程
  • 为2020年的订单添加匹配阶段
  • 添加查找阶段以链接集合
  • 添加设置阶段以创建新的文档字段
  • 添加删除阶段以删除不需要的字段
  • 运行聚合管道
  • 解释结果

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

此聚合操作执行一对一连接。当某个集合中的一个文档的字段值与另一个集合中具有相同字段值的单个文档相匹配时,就会发生一对一连接。聚合通过字段值匹配这些文档,并将来自两个来源的信息合并到一个结果中。

提示

一对一连接不需要文档之间存在一对一关系。要了解更多关于这种数据关系的信息,请参阅维基百科关于一对一(数据模型).

本教程演示了如何将描述产品信息的集合数据与描述客户订单的另一个集合数据相结合。结果显示了2020年所有订单的列表,包括每个订单相关的产品详细信息。

此示例使用两个集合

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

  • products:包含描述商店销售产品的文档

一个订单只能包含一个产品,因此聚合使用一对一连接将订单文档与产品的文档匹配。通过在两个集合的文档中都存在的字段 product_id 将集合连接起来。

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

设置应用程序后,通过向应用程序添加以下代码访问 ordersproducts 集合

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

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

await ordersColl.deleteMany({});
const orderData = [
{
customer_id: "elise_smith@myemail.com",
orderdate: new Date("2020-05-30T08:35:52Z"),
product_id: "a1b2c3d4",
value: 431.43,
},
{
customer_id: "tj@wheresmyemail.com",
orderdate: new Date("2019-05-28T19:13:32Z"),
product_id: "z9y8x7w6",
value: 5.01,
},
{
customer_id: "oranieri@warmmail.com",
orderdate: new Date("2020-01-01T08:25:37Z"),
product_id: "ff11gg22hh33",
value: 63.13,
},
{
customer_id: "jjones@tepidmail.com",
orderdate: new Date("2020-12-26T08:55:46Z"),
product_id: "a1b2c3d4",
value: 429.65,
},
];
await ordersColl.insertMany(orderData);

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

await productsColl.deleteMany({});
const productData = [
{
id: "a1b2c3d4",
name: "Asus Laptop",
category: "ELECTRONICS",
description: "Good value laptop for students",
},
{
id: "z9y8x7w6",
name: "The Day Of The Triffids",
category: "BOOKS",
description: "Classic post-apocalyptic novel",
},
{
id: "ff11gg22hh33",
name: "Morphy Richardds Food Mixer",
category: "KITCHENWARE",
description: "Luxury mixer turning good cakes into great",
},
{
id: "pqr678st",
name: "Karcher Hose Set",
category: "GARDEN",
description: "Hose + nosels + winder for tidy storage",
},
];
await productsColl.insertMany(productData);
1

添加匹配2020年下订单的 $match 阶段

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

接下来,添加一个 $lookup 阶段。该 $lookup 阶段将 orders 集合中的 product_id 字段与 products 集合中的 id 字段进行连接

pipeline.push({
$lookup: {
from: "products",
localField: "product_id",
foreignField: "id",
as: "product_mapping",
},
});
3

接下来,向管道中添加两个$set阶段。

第一个$set阶段将product_mapping字段设置为在前一个$lookup阶段创建的product_mapping对象中的第一个元素。

第二个$set阶段根据product_mapping对象字段中的值创建两个新字段,分别是product_nameproduct_category

pipeline.push(
{
$set: {
product_mapping: { $first: "$product_mapping" },
},
},
{
$set: {
product_name: "$product_mapping.name",
product_category: "$product_mapping.category",
},
}
);

提示

因为这是一个一对一的连接,所以$lookup阶段只向输入文档添加一个数组元素。管道使用$first运算符从这个元素检索数据。

4

最后,添加一个$unset阶段。该$unset阶段从文档中删除不必要的字段

pipeline.push({ $unset: ["_id", "product_id", "product_mapping"] });
5

将以下代码添加到您的应用程序末尾,以在orders集合上执行聚合

const aggregationResult = await ordersColl.aggregate(pipeline);

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

node agg_tutorial.js
6

聚合结果包含三个文档。这些文档代表了2020年发生的客户订单,其中包含了订单产品的 product_nameproduct_category

{
customer_id: 'elise_smith@myemail.com',
orderdate: 2020-05-30T08:35:52.000Z,
value: 431.43,
product_name: 'Asus Laptop',
product_category: 'ELECTRONICS'
}
{
customer_id: 'oranieri@warmmail.com',
orderdate: 2020-01-01T08:25:37.000Z,
value: 63.13,
product_name: 'Morphy Richardds Food Mixer',
product_category: 'KITCHENWARE'
}
{
customer_id: 'jjones@tepidmail.com',
orderdate: 2020-12-26T08:55:46.000Z,
value: 429.65,
product_name: 'Asus Laptop',
product_category: 'ELECTRONICS'
}

结果包含来自 orders 集合和 products 集合的文档的字段,通过匹配每个原始文档中存在的 product_id 字段进行连接。

要查看本教程的完整代码,请参阅GitHub上的 完成的一对一连接应用

返回

解包数组和分组