Database Manual / Aggregation Operations / Aggregation Pipeline / Complete Pipeline Examples

Perform Multi-Field Joins执行多字段联接

This tutorial illustrates how to construct an aggregation pipeline, perform the aggregation on a collection, and display the results using the language of your choice.本教程说明了如何构建聚合管道,对集合执行聚合,并使用您选择的语言显示结果。

About This Task关于此任务

This tutorial demonstrates how to combine data from a collection that describes product information with another collection that describes customer orders. The results show a list of products ordered in 2020 and details about each order.本教程演示了如何将描述产品信息的集合的数据与描述客户订单的另一个集合的数据组合在一起。结果显示了2020年订购的产品列表以及每个订单的详细信息。

This aggregation performs a multi-field join by using $lookup. A multi-field join occurs when there are multiple corresponding fields in the documents of two collections. 此聚合通过使用$lookup执行多字段联接。当两个集合的文档中有多个对应的字段时,就会发生多字段联接。The aggregation matches these documents on the corresponding fields and combines information from both into one document.聚合将这些文档在相应的字段中进行匹配,并将两者中的信息组合到一个文档中。

Before You Begin开始之前


Use the Select your language drop-down menu in the upper-right to set the language of the following examples or select MongoDB Shell.使用右上角的“选择语言”下拉菜单设置以下示例的语言,或选择MongoDB Shell。


MongoDB Shell

This example uses two collections:此示例使用两个集合:

  • products, which contains documents describing the products that a shop sellsproducts,其中包含描述商店销售产品的文档
  • orders, which contains documents describing individual orders for products in a shop,其中包含描述商店中产品的单个订单的文档

An order can only contain one product. The aggregation uses a multi-field join to match a product document to documents representing orders of that product. 一个订单只能包含一个产品。聚合使用多字段联接将产品文档与表示该产品订单的文档相匹配。The aggregation joins collections by the name and variation fields in documents in the products collection, corresponding to the product_name and product_variation fields in documents in the orders collection.聚合通过products集合中文档中的namevariation(变体)字段连接集合,对应于orders集合中文档的product_nameproduct_variation字段。

To create the orders and products collections, use the insertMany() method:要创建ordersproducts集合,请使用insertMany()方法:

db.orders.insertMany( [
{
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,
}
] )
db.products.insertMany( [
{
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"
}
] )
C

Create the Template App创建模板应用程序

Before you begin following this aggregation tutorial, you must set up a new C app. You can use this app to connect to a MongoDB deployment, insert sample data into MongoDB, and run the aggregation pipeline.在开始学习此聚合教程之前,您必须设置一个新的C应用程序。您可以使用此应用程序连接到MongoDB部署,将示例数据插入MongoDB,并运行聚合管道。

Tip

To learn how to install the driver and connect to MongoDB, see the Get Started with the C Driver guide.要了解如何安装驱动程序并连接到MongoDB,请参阅C驱动程序入门指南

To learn more about performing aggregations in the C Driver, see the Aggregation guide.要了解有关在C驱动程序中执行聚合的更多信息,请参阅聚合指南

After you install the driver, create a file called agg-tutorial.c. Paste the following code in this file to create an app template for the aggregation tutorials.安装驱动程序后,创建一个名为agg-tutorial.c的文件。将以下代码粘贴到此文件中,为聚合教程创建应用程序模板。

Important

In the following code, read the code comments to find the sections of the code that you must modify for the tutorial you are following.在下面的代码中,阅读代码注释,找到您必须为正在学习的教程修改的代码部分。

If you attempt to run the code without making any changes, you will encounter a connection error.如果您尝试在不进行任何更改的情况下运行代码,您将遇到连接错误。

#include <stdio.h>
#include <bson/bson.h>
#include <mongoc/mongoc.h>

int main(void)
{
mongoc_init();

// Replace the placeholder with your connection string.
char *uri = "<connection string>";
mongoc_client_t* client = mongoc_client_new(uri);

// Get a reference to relevant collections.
// ... mongoc_collection_t *some_coll = mongoc_client_get_collection(client, "agg_tutorials_db", "some_coll");
// ... mongoc_collection_t *another_coll = mongoc_client_get_collection(client, "agg_tutorials_db", "another_coll");

// Delete any existing documents in collections if needed.
// ... {
// ... bson_t *filter = bson_new();
// ... bson_error_t error;
// ... if (!mongoc_collection_delete_many(some_coll, filter, NULL, NULL, &error))
// ... {
// ... fprintf(stderr, "Delete error: %s\n", error.message);
// ... }
// ... bson_destroy(filter);
// ... }

// Insert sample data into the collection or collections.
// ... {
// ... size_t num_docs = ...;
// ... bson_t *docs[num_docs];
// ...
// ... docs[0] = ...;
// ...
// ... bson_error_t error;
// ... if (!mongoc_collection_insert_many(some_coll, (const bson_t **)docs, num_docs, NULL, NULL, &error))
// ... {
// ... fprintf(stderr, "Insert error: %s\n", error.message);
// ... }
// ...
// ... for (int i = 0; i < num_docs; i++)
// ... {
// ... bson_destroy(docs[i]);
// ... }
// ... }

{
const bson_t *doc;

// Add code to create pipeline stages.
bson_t *pipeline = BCON_NEW("pipeline", "[",
// ... Add pipeline stages here.
"]");

// Run the aggregation.
// ... mongoc_cursor_t *results = mongoc_collection_aggregate(some_coll, MONGOC_QUERY_NONE, pipeline, NULL, NULL);

bson_destroy(pipeline);

// Print the aggregation results.
while (mongoc_cursor_next(results, &doc))
{
char *str = bson_as_canonical_extended_json(doc, NULL);
printf("%s\n", str);
bson_free(str);
}
bson_error_t error;
if (mongoc_cursor_error(results, &error))
{
fprintf(stderr, "Aggregation error: %s\n", error.message);
}

mongoc_cursor_destroy(results);
}

// Clean up resources.
// ... mongoc_collection_destroy(some_coll);
mongoc_client_destroy(client);
mongoc_cleanup();

return EXIT_SUCCESS;
}

For every tutorial, you must replace the connection string placeholder with your deployment's connection string.对于每个教程,您必须将连接字符串占位符替换为部署的连接字符串。

Tip

To learn how to locate your deployment's connection string, see the Create a Connection String step of the C Get Started guide.要了解如何定位部署的连接字符串,请参阅《C入门》指南的创建连接字符串步骤。

For example, if your connection string is "mongodb+srv://mongodb-example:27017", your connection string assignment resembles the following:例如,如果连接字符串是"mongodb+srv://mongodb-example:27017",连接字符串分配类似于以下内容:

char *uri = "mongodb+srv://mongodb-example:27017";

Create the Collection创建集合

This example uses two collections:此示例使用两个集合:

  • products, which contains documents describing the products that a shop sells,其中包含描述商店销售产品的文档
  • orders, which contains documents describing individual orders for products in a shop,其中包含描述商店中产品的单个订单的文档

An order can only contain one product. The aggregation uses a multi-field join to match a product document to documents representing orders of that product. 一个订单只能包含一个产品。聚合使用多字段联接将产品文档与表示该产品订单的文档相匹配。The aggregation joins collections by the name and variation fields in documents in the products collection, corresponding to the product_name and product_variation fields in documents in the orders collection.聚合通过products集合中文档中的namevariation(变体)字段连接集合,对应于orders集合中文档的product_nameproduct_variation字段。

To create the products and orders collections and insert the sample data, add the following code to your application:要创建productsorders集合并插入示例数据,请将以下代码添加到应用程序中:

mongoc_collection_t *products = mongoc_client_get_collection(client, "agg_tutorials_db", "products");
mongoc_collection_t *orders = mongoc_client_get_collection(client, "agg_tutorials_db", "orders");

{
bson_t *filter = bson_new();
bson_error_t error;
if (!mongoc_collection_delete_many(products, filter, NULL, NULL, &error))
{
fprintf(stderr, "Delete error: %s\n", error.message);
}
if (!mongoc_collection_delete_many(orders, filter, NULL, NULL, &error))
{
fprintf(stderr, "Delete error: %s\n", error.message);
}
bson_destroy(filter);
}

{
size_t num_docs = 5;
bson_t *product_docs[num_docs];

product_docs[0] = BCON_NEW(
"name", BCON_UTF8("Asus Laptop"),
"variation", BCON_UTF8("Ultra HD"),
"category", BCON_UTF8("ELECTRONICS"),
"description", BCON_UTF8("Great for watching movies"));

product_docs[1] = BCON_NEW(
"name", BCON_UTF8("Asus Laptop"),
"variation", BCON_UTF8("Standard Display"),
"category", BCON_UTF8("ELECTRONICS"),
"description", BCON_UTF8("Good value laptop for students"));

product_docs[2] = BCON_NEW(
"name", BCON_UTF8("The Day Of The Triffids"),
"variation", BCON_UTF8("1st Edition"),
"category", BCON_UTF8("BOOKS"),
"description", BCON_UTF8("Classic post-apocalyptic novel"));

product_docs[3] = BCON_NEW(
"name", BCON_UTF8("The Day Of The Triffids"),
"variation", BCON_UTF8("2nd Edition"),
"category", BCON_UTF8("BOOKS"),
"description", BCON_UTF8("Classic post-apocalyptic novel"));

product_docs[4] = BCON_NEW(
"name", BCON_UTF8("Morphy Richards Food Mixer"),
"variation", BCON_UTF8("Deluxe"),
"category", BCON_UTF8("KITCHENWARE"),
"description", BCON_UTF8("Luxury mixer turning good cakes into great"));

bson_error_t error;
if (!mongoc_collection_insert_many(products, (const bson_t **)product_docs, num_docs, NULL, NULL, &error))
{
fprintf(stderr, "Insert error: %s\n", error.message);
}

for (int i = 0; i < num_docs; i++)
{
bson_destroy(product_docs[i]);
}
}

{
size_t num_docs = 4;
bson_t *order_docs[num_docs];

order_docs[0] = BCON_NEW(
"customer_id", BCON_UTF8("elise_smith@myemail.com"),
"orderdate", BCON_DATE_TIME(1590822952000UL), // 2020-05-30T08:35:52Z
"product_name", BCON_UTF8("Asus Laptop"),
"product_variation", BCON_UTF8("Standard Display"),
"value", BCON_DOUBLE(431.43));

order_docs[1] = BCON_NEW(
"customer_id", BCON_UTF8("tj@wheresmyemail.com"),
"orderdate", BCON_DATE_TIME(1559063612000UL), // 2019-05-28T19:13:32Z
"product_name", BCON_UTF8("The Day Of The Triffids"),
"product_variation", BCON_UTF8("2nd Edition"),
"value", BCON_DOUBLE(5.01));

order_docs[2] = BCON_NEW(
"customer_id", BCON_UTF8("oranieri@warmmail.com"),
"orderdate", BCON_DATE_TIME(1577869537000UL), // 2020-01-01T08:25:37Z
"product_name", BCON_UTF8("Morphy Richards Food Mixer"),
"product_variation", BCON_UTF8("Deluxe"),
"value", BCON_DOUBLE(63.13));

order_docs[3] = BCON_NEW(
"customer_id", BCON_UTF8("jjones@tepidmail.com"),
"orderdate", BCON_DATE_TIME(1608976546000UL), // 2020-12-26T08:55:46Z
"product_name", BCON_UTF8("Asus Laptop"),
"product_variation", BCON_UTF8("Standard Display"),
"value", BCON_DOUBLE(429.65));

bson_error_t error;
if (!mongoc_collection_insert_many(orders, (const bson_t **)order_docs, num_docs, NULL, NULL, &error))
{
fprintf(stderr, "Insert error: %s\n", error.message);
}

for (int i = 0; i < num_docs; i++)
{
bson_destroy(order_docs[i]);
}
}
C++11

Create the Template App创建模板应用程序

Before you begin following an aggregation tutorial, you must set up a new C++ app. You can use this app to connect to a MongoDB deployment, insert sample data into MongoDB, and run the aggregation pipeline.在开始学习聚合教程之前,您必须设置一个新的C++应用程序。您可以使用此应用程序连接到MongoDB部署,将示例数据插入MongoDB,并运行聚合管道。

Tip

To learn how to install the driver and connect to MongoDB, see the Get Started with C++ tutorial.要了解如何安装驱动程序并连接到MongoDB,请参阅C++入门教程

To learn more about using the C++ driver, see the API documentation.要了解有关使用C++驱动程序的更多信息,请参阅API文档

To learn more about performing aggregations in the C++ Driver, see the Aggregation guide.要了解有关在C++驱动程序中执行聚合的更多信息,请参阅聚合指南

After you install the driver, create a file called agg-tutorial.cpp. Paste the following code in this file to create an app template for the aggregation tutorials.安装驱动程序后,创建一个名为agg-tutorial.cpp的文件。将以下代码粘贴到此文件中,为聚合教程创建应用程序模板。

Important

In the following code, read the code comments to find the sections of the code that you must modify for the tutorial you are following.在下面的代码中,阅读代码注释,找到您必须为正在学习的教程修改的代码部分。

If you attempt to run the code without making any changes, you will encounter a connection error.如果您尝试在不进行任何更改的情况下运行代码,您将遇到连接错误。

#include <iostream>
#include <bsoncxx/builder/basic/document.hpp>
#include <bsoncxx/builder/basic/kvp.hpp>
#include <bsoncxx/json.hpp>
#include <mongocxx/client.hpp>
#include <mongocxx/instance.hpp>
#include <mongocxx/pipeline.hpp>
#include <mongocxx/uri.hpp>
#include <chrono>

using bsoncxx::builder::basic::kvp;
using bsoncxx::builder::basic::make_document;
using bsoncxx::builder::basic::make_array;

int main() {
mongocxx::instance instance;

// Replace the placeholder with your connection string.
mongocxx::uri uri("<connection string>");
mongocxx::client client(uri);

auto db = client["agg_tutorials_db"];
// Delete existing data in the database, if necessary.
db.drop();

// Get a reference to relevant collections.
// ... auto some_coll = db["..."];
// ... auto another_coll = db["..."];

// Insert sample data into the collection or collections.
// ... some_coll.insert_many(docs);

// Create an empty pipelne.
mongocxx::pipeline pipeline;

// Add code to create pipeline stages.
// pipeline.match(make_document(...));

// Run the aggregation and print the results.
auto cursor = orders.aggregate(pipeline);
for (auto&& doc : cursor) {
std::cout << bsoncxx::to_json(doc, bsoncxx::ExtendedJsonMode::k_relaxed) << std::endl;
}
}

For every tutorial, you must replace the connection string placeholder with your deployment's connection string.对于每个教程,您必须将连接字符串占位符替换为部署的连接字符串。

Tip

To learn how to locate your deployment's connection string, see the Create a Connection String step of the C++ Get Started tutorial.要了解如何定位部署的连接字符串,请参阅C++入门教程的创建连接字符串步骤。

For example, if your connection string is "mongodb+srv://mongodb-example:27017", your connection string assignment resembles the following:例如,如果连接字符串是"mongodb+srv://mongodb-example:27017",连接字符串分配类似于以下内容:

mongocxx::uri uri{"mongodb+srv://mongodb-example:27017"};

Create the Collection创建集合

This example uses two collections:此示例使用两个集合:

  • products, which contains documents describing the products that a shop sells,其中包含描述商店销售产品的文档
  • orders, which contains documents describing individual orders for products in a shop,其中包含描述商店中产品的单个订单的文档

An order can only contain one product. The aggregation uses a multi-field join to match a product document to documents representing orders of that product. 一个订单只能包含一个产品。聚合使用多字段联接将产品文档与表示该产品订单的文档相匹配。The aggregation joins collections by the name and variation fields in documents in the products collection, corresponding to the product_name and product_variation fields in documents in the orders collection.聚合通过products集合中文档中的namevariation(变体)字段连接集合,对应于orders集合中文档的product_nameproduct_variation字段。

To create the products and orders collections and insert the sample data, add the following code to your application:要创建productsorders集合并插入示例数据,请将以下代码添加到应用程序中:

auto products = db["products"];
auto orders = db["orders"];

std::vector<bsoncxx::document::value> product_docs = {
bsoncxx::from_json(R"({
"name": "Asus Laptop",
"variation": "Ultra HD",
"category": "ELECTRONICS",
"description": "Great for watching movies"
})"),
bsoncxx::from_json(R"({
"name": "Asus Laptop",
"variation": "Standard Display",
"category": "ELECTRONICS",
"description": "Good value laptop for students"
})"),
bsoncxx::from_json(R"({
"name": "The Day Of The Triffids",
"variation": "1st Edition",
"category": "BOOKS",
"description": "Classic post-apocalyptic novel"
})"),
bsoncxx::from_json(R"({
"name": "The Day Of The Triffids",
"variation": "2nd Edition",
"category": "BOOKS",
"description": "Classic post-apocalyptic novel"
})"),
bsoncxx::from_json(R"({
"name": "Morphy Richards Food Mixer",
"variation": "Deluxe",
"category": "KITCHENWARE",
"description": "Luxury mixer turning good cakes into great"
})")
};

products.insert_many(product_docs); // Might throw an exception

std::vector<bsoncxx::document::value> order_docs = {
bsoncxx::from_json(R"({
"customer_id": "elise_smith@myemail.com",
"orderdate": {"$date": 1590821752000},
"product_name": "Asus Laptop",
"product_variation": "Standard Display",
"value": 431.43
})"),
bsoncxx::from_json(R"({
"customer_id": "tj@wheresmyemail.com",
"orderdate": {"$date": 1559062412000},
"product_name": "The Day Of The Triffids",
"product_variation": "2nd Edition",
"value": 5.01
})"),
bsoncxx::from_json(R"({
"customer_id": "oranieri@warmmail.com",
"orderdate": {"$date": 1577861137000},
"product_name": "Morphy Richards Food Mixer",
"product_variation": "Deluxe",
"value": 63.13
})"),
bsoncxx::from_json(R"({
"customer_id": "jjones@tepidmail.com",
"orderdate": {"$date": 1608972946000},
"product_name": "Asus Laptop",
"product_variation": "Standard Display",
"value": 429.65
})")
};

orders.insert_many(order_docs); // Might throw an exception
C#

Create the Template App创建模板应用程序

Before you begin following this aggregation tutorial, you must set up a new C#/.NET app. You can use this app to connect to a MongoDB deployment, insert sample data into MongoDB, and run the aggregation pipeline.在开始学习此聚合教程之前,您必须设置一个新的C#/NET应用程序。您可以使用此应用程序连接到MongoDB部署,将示例数据插入MongoDB,并运行聚合管道。

Tip

To learn how to install the driver and connect to MongoDB, see the C#/.NET Driver Quick Start guide.要了解如何安装驱动程序并连接到MongoDB,请参阅C#/.NET驱动程序快速入门指南

To learn more about performing aggregations in the C#/.NET Driver, see the Aggregation guide.要了解有关在C#/NET驱动程序中执行聚合的更多信息,请参阅聚合指南

After you install the driver, paste the following code into your Program.cs file to create an app template for the aggregation tutorials.安装驱动程序后,将以下代码粘贴到Programs文件中,为聚合教程创建应用程序模板。

Important

In the following code, read the code comments to find the sections of the code that you must modify for the tutorial you are following.在下面的代码中,阅读代码注释,找到您必须为正在学习的教程修改的代码部分。

If you attempt to run the code without making any changes, you will encounter a connection error.如果您尝试在不进行任何更改的情况下运行代码,您将遇到连接错误。

using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
using MongoDB.Driver;

// Define data model classes.
// ... public class MyClass { ... }

// Replace the placeholder with your connection string.
var uri = "<connection string>";
var client = new MongoClient(uri);
var aggDB = client.GetDatabase("agg_tutorials_db");

// Get a reference to relevant collections.
// ... var someColl = aggDB.GetCollection<MyClass>("someColl");
// ... var anotherColl = aggDB.GetCollection<MyClass>("anotherColl");

// Delete any existing documents in collections if needed.
// ... someColl.DeleteMany(Builders<MyClass>.Filter.Empty);

// Insert sample data into the collection or collections.
// ... someColl.InsertMany(new List<MyClass> { ... });

// Add code to chain pipeline stages to the Aggregate() method.
// ... var results = someColl.Aggregate().Match(...);

// Print the aggregation results.
foreach (var result in results.ToList())
{
Console.WriteLine(result);
}

For every tutorial, you must replace the connection string placeholder with your deployment's connection string.对于每个教程,您必须将连接字符串占位符替换为部署的连接字符串。

Tip

To learn how to locate your deployment's connection string, see the Set Up a Free Tier Cluster in Atlas step of the C# Quick Start guide.要了解如何定位部署的连接字符串,请参阅《C#快速入门》指南的在Atlas中设置免费层集群步骤。

For example, if your connection string is "mongodb+srv://mongodb-example:27017", your connection string assignment resembles the following:例如,如果连接字符串是"mongodb+srv://mongodb-example:27017",连接字符串分配类似于以下内容:

var uri = "mongodb+srv://mongodb-example:27017";

Create the Collection创建集合

This example uses two collections:此示例使用两个集合:

  • products, which contains documents describing the products that a shop sells,其中包含描述商店销售产品的文档
  • orders, which contains documents describing individual orders for products in a shop,其中包含描述商店中产品的单个订单的文档

An order can only contain one product. The aggregation uses a multi-field join to match a product document to documents representing orders of that product. 一个订单只能包含一个产品。聚合使用多字段联接将产品文档与表示该产品订单的文档相匹配。The aggregation joins collections by the Name and Variation fields in documents in the products collection, corresponding to the ProductName and ProductVariation fields in documents in the orders collection.聚合通过products集合中文档中的NameVariation(变体)字段连接集合,对应于orders集合中文档的ProductNameProductVariation字段。

First, create C# classes to model the data in the products and orders collections:首先,创建C#类来对productsorders集合中的数据进行建模:

public class Product
{
[BsonId]
public ObjectId Id { get; set; }

public string Name { get; set; } = "";
public string Variation { get; set; } = "";
public string Category { get; set; } = "";
public string Description { get; set; } = "";
}

public class Order
{
[BsonId]
public ObjectId Id { get; set; }

public required string CustomerId { get; set; }
public DateTime OrderDate { get; set; }
public string ProductName { get; set; } = "";
public string ProductVariation { get; set; } = "";
public double Value { get; set; }
}

To create the products and orders collections and insert the sample data, add the following code to your application:要创建productsorders集合并插入示例数据,请将以下代码添加到应用程序中:

var orders = aggDB.GetCollection<Order>("orders");
var products = aggDB.GetCollection<Product>("products");

products.InsertMany(new List<Product>
{
new Product
{
Name = "Asus Laptop",
Variation = "Ultra HD",
Category = "ELECTRONICS",
Description = "Great for watching movies"
},
new Product
{
Name = "Asus Laptop",
Variation = "Standard Display",
Category = "ELECTRONICS",
Description = "Good value laptop for students"
},
new Product
{
Name = "The Day Of The Triffids",
Variation = "1st Edition",
Category = "BOOKS",
Description = "Classic post-apocalyptic novel"
},
new Product
{
Name = "The Day Of The Triffids",
Variation = "2nd Edition",
Category = "BOOKS",
Description = "Classic post-apocalyptic novel"
},
new Product
{
Name = "Morphy Richards Food Mixer",
Variation = "Deluxe",
Category = "KITCHENWARE",
Description = "Luxury mixer turning good cakes into great"
}
});

orders.InsertMany(new List<Order>
{
new Order
{
CustomerId = "elise_smith@myemail.com",
OrderDate = DateTime.Parse("2020-05-30T08:35:52Z"),
ProductName = "Asus Laptop",
ProductVariation = "Standard Display",
Value = 431.43
},
new Order
{
CustomerId = "tj@wheresmyemail.com",
OrderDate = DateTime.Parse("2019-05-28T19:13:32Z"),
ProductName = "The Day Of The Triffids",
ProductVariation = "2nd Edition",
Value = 5.01
},
new Order
{
CustomerId = "oranieri@warmmail.com",
OrderDate = DateTime.Parse("2020-01-01T08:25:37Z"),
ProductName = "Morphy Richards Food Mixer",
ProductVariation = "Deluxe",
Value = 63.13
},
new Order
{
CustomerId = "jjones@tepidmail.com",
OrderDate = DateTime.Parse("2020-12-26T08:55:46Z"),
ProductName = "Asus Laptop",
ProductVariation = "Standard Display",
Value = 429.65
}
});
Go

Create the Template App创建模板应用程序

Before you begin following this aggregation tutorial, you must set up a new Go app. You can use this app to connect to a MongoDB deployment, insert sample data into MongoDB, and run the aggregation pipeline.在开始学习此聚合教程之前,您必须设置一个新的Go应用程序。您可以使用此应用程序连接到MongoDB部署,将示例数据插入MongoDB,并运行聚合管道。

Tip

To learn how to install the driver and connect to MongoDB, see the Go Driver Quick Start guide.要了解如何安装驱动程序并连接到MongoDB,请参阅Go驱动程序快速入门指南。

To learn more about performing aggregations in the Go Driver, see the Aggregation guide.要了解有关在Go驱动程序中执行聚合的更多信息,请参阅聚合指南

After you install the driver, create a file called agg_tutorial.go. Paste the following code in this file to create an app template for the aggregation tutorials.安装驱动程序后,创建一个名为agg_tutorial.go的文件。将以下代码粘贴到此文件中,为聚合教程创建应用程序模板。

Important

In the following code, read the code comments to find the sections of the code that you must modify for the tutorial you are following.在下面的代码中,阅读代码注释,找到您必须为正在学习的教程修改的代码部分。

If you attempt to run the code without making any changes, you will encounter a connection error.如果您尝试在不进行任何更改的情况下运行代码,您将遇到连接错误。

package main

import (
"context"
"fmt"
"log"

"go.mongodb.org/mongo-driver/v2/bson"
"go.mongodb.org/mongo-driver/v2/mongo"
"go.mongodb.org/mongo-driver/v2/mongo/options"
)

// Define structs.
// type MyStruct struct { ... }

func main() {
ctx := context.Background()
// Replace the placeholder with your connection string.
const uri = "<connection string>"

client, err := mongo.Connect(options.Client().ApplyURI(uri))
if err != nil {
log.Fatal(err)
}

defer func() {
if err = client.Disconnect(ctx); err != nil {
log.Fatal(err)
}
}()

aggDB := client.Database("agg_tutorials_db")

// Get a reference to relevant collections.
// ... someColl := aggDB.Collection("...")
// ... anotherColl := aggDB.Collection("...")

// Delete any existing documents in collections if needed.
// ... someColl.DeleteMany(cxt, bson.D{})

// Insert sample data into the collection or collections.
// ... _, err = someColl.InsertMany(...)

// Add code to create pipeline stages.
// ... myStage := bson.D{{...}}

// Create a pipeline that includes the stages.
// ... pipeline := mongo.Pipeline{...}

// Run the aggregation.
// ... cursor, err := someColl.Aggregate(ctx, pipeline)

if err != nil {
log.Fatal(err)
}

defer func() {
if err := cursor.Close(ctx); err != nil {
log.Fatalf("failed to close cursor: %v", err)
}
}()

// Decode the aggregation results.
var results []bson.D
if err = cursor.All(ctx, &results); err != nil {
log.Fatalf("failed to decode results: %v", err)
}

// Print the aggregation results.
for _, result := range results {
res, _ := bson.MarshalExtJSON(result, false, false)
fmt.Println(string(res))
}
}

For every tutorial, you must replace the connection string placeholder with your deployment's connection string.对于每个教程,您必须将连接字符串占位符替换为部署的连接字符串。

Tip

To learn how to locate your deployment's connection string, see the Create a MongoDB Cluster step of the Go Quick Start guide.要了解如何定位部署的连接字符串,请参阅Go快速入门指南的创建MongoDB集群步骤

For example, if your connection string is "mongodb+srv://mongodb-example:27017", your connection string assignment resembles the following:例如,如果连接字符串是"mongodb+srv://mongodb-example:27017",连接字符串分配类似于以下内容:

const uri = "mongodb+srv://mongodb-example:27017";

Create the Collection创建集合

This example uses two collections:此示例使用两个集合:

  • products, which contains documents describing the products that a shop sells,其中包含描述商店销售产品的文档
  • orders, which contains documents describing individual orders for products in a shop,其中包含描述商店中产品的单个订单的文档

An order can only contain one product. The aggregation uses a multi-field join to match a product document to documents representing orders of that product. 一个订单只能包含一个产品。聚合使用多字段联接将产品文档与表示该产品订单的文档相匹配。The aggregation joins collections by the name and variation fields in documents in the products collection, corresponding to the product_name and product_variation fields in documents in the orders collection.聚合通过products集合中文档中的namevariation(变体)字段连接集合,对应于orders集合中文档的product_nameproduct_variation字段。

First, create Go structs to model the data in the products and orders collections:首先,创建Go结构体来对productsorders集合中的数据进行建模:

type Product struct {
Name string
Variation string
Category string
Description string
}

type Order struct {
CustomerID string `bson:"customer_id"`
OrderDate bson.DateTime `bson:"orderdate"`
ProductName string `bson:"product_name"`
ProductVariation string `bson:"product_variation"`
Value float32 `bson:"value"`
}

To create the products and orders collections and insert the sample data, add the following code to your application:要创建productsorders集合并插入示例数据,请将以下代码添加到应用程序中:

products := aggDB.Collection("products")
orders := aggDB.Collection("orders")

_, err = products.InsertMany(ctx, []interface{}{
Product{
Name: "Asus Laptop",
Variation: "Ultra HD",
Category: "ELECTRONICS",
Description: "Great for watching movies",
},
Product{
Name: "Asus Laptop",
Variation: "Standard Display",
Category: "ELECTRONICS",
Description: "Good value laptop for students",
},
Product{
Name: "The Day Of The Triffids",
Variation: "1st Edition",
Category: "BOOKS",
Description: "Classic post-apocalyptic novel",
},
Product{
Name: "The Day Of The Triffids",
Variation: "2nd Edition",
Category: "BOOKS",
Description: "Classic post-apocalyptic novel",
},
Product{
Name: "Morphy Richards Food Mixer",
Variation: "Deluxe",
Category: "KITCHENWARE",
Description: "Luxury mixer turning good cakes into great",
},
})
if err != nil {
log.Fatal(err)
}

_, err = orders.InsertMany(ctx, []interface{}{
Order{
CustomerID: "elise_smith@myemail.com",
OrderDate: bson.NewDateTimeFromTime(time.Date(2020, 5, 30, 8, 35, 52, 0, time.UTC)),
ProductName: "Asus Laptop",
ProductVariation: "Standard Display",
Value: 431.43,
},
Order{
CustomerID: "tj@wheresmyemail.com",
OrderDate: bson.NewDateTimeFromTime(time.Date(2019, 5, 28, 19, 13, 32, 0, time.UTC)),
ProductName: "The Day Of The Triffids",
ProductVariation: "2nd Edition",
Value: 5.01,
},
Order{
CustomerID: "oranieri@warmmail.com",
OrderDate: bson.NewDateTimeFromTime(time.Date(2020, 1, 1, 8, 25, 37, 0, time.UTC)),
ProductName: "Morphy Richards Food Mixer",
ProductVariation: "Deluxe",
Value: 63.13,
},
Order{
CustomerID: "jjones@tepidmail.com",
OrderDate: bson.NewDateTimeFromTime(time.Date(2020, 12, 26, 8, 55, 46, 0, time.UTC)),
ProductName: "Asus Laptop",
ProductVariation: "Standard Display",
Value: 429.65,
},
})
if err != nil {

log.Fatal(err)
}
Java(Sync)

Create the Template App创建模板应用程序

Before you begin following an aggregation tutorial, you must set up a new Java app. You can use this app to connect to a MongoDB deployment, insert sample data into MongoDB, and run the aggregation pipeline.在开始学习聚合教程之前,您必须设置一个新的Java应用程序。您可以使用此应用程序连接到MongoDB部署,将示例数据插入MongoDB,并运行聚合管道。

Tip

To learn how to install the driver and connect to MongoDB, see the Get Started with the Java Driver guide.要了解如何安装驱动程序并连接到MongoDB,请参阅Java驱动程序入门指南

To learn more about performing aggregations in the Java Sync Driver, see the Aggregation guide.要了解有关在Java同步驱动程序中执行聚合的更多信息,请参阅聚合指南

After you install the driver, create a file called AggTutorial.java. Paste the following code in this file to create an app template for the aggregation tutorials.安装驱动程序后,创建一个名为AggTutorial.java的文件。将以下代码粘贴到此文件中,为聚合教程创建应用程序模板。

Important

In the following code, read the code comments to find the sections of the code that you must modify for the tutorial you are following.在下面的代码中,阅读代码注释,找到您必须为正在学习的教程修改的代码部分。

If you attempt to run the code without making any changes, you will encounter a connection error.如果您尝试在不进行任何更改的情况下运行代码,您将遇到连接错误。

package org.example;

// Modify imports for each tutorial as needed.
import com.mongodb.client.*;
import com.mongodb.client.model.Accumulators;
import com.mongodb.client.model.Aggregates;
import com.mongodb.client.model.Field;
import com.mongodb.client.model.Filters;
import com.mongodb.client.model.Sorts;
import com.mongodb.client.model.Variable;
import org.bson.Document;
import org.bson.conversions.Bson;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class AggTutorial {
public static void main(String[] args) {
// Replace the placeholder with your connection string.
String uri = "<connection string>";

try (MongoClient mongoClient = MongoClients.create(uri)) {
MongoDatabase aggDB = mongoClient.getDatabase("agg_tutorials_db");

// Get a reference to relevant collections.
// ... MongoCollection<Document> someColl = ...
// ... MongoCollection<Document> anotherColl = ...

// Insert sample data into the collection or collections.
// ... someColl.insertMany(...);

// Create an empty pipeline array.
List<Bson> pipeline = new ArrayList<>();

// Add code to create pipeline stages.
// ... pipeline.add(...);

// Run the aggregation.
// ... AggregateIterable<Document> aggregationResult =
// someColl.aggregate(pipeline);

// Print the aggregation results.
for (Document document : aggregationResult) {
System.out.println(document.toJson());
}
}
}
}

For every tutorial, you must replace the connection string placeholder with your deployment's connection string.对于每个教程,您必须将连接字符串占位符替换为部署的连接字符串。

Tip

To learn how to locate your deployment's connection string, see the Create a Connection String step of the Java Sync Quick Start guide.要了解如何定位部署的连接字符串,请参阅《Java Sync快速入门》指南的创建连接字符串步骤。

For example, if your connection string is "mongodb+srv://mongodb-example:27017", your connection string assignment resembles the following:例如,如果连接字符串是"mongodb+srv://mongodb-example:27017",连接字符串分配类似于以下内容:

String uri = "mongodb+srv://mongodb-example:27017";

Create the Collection创建集合

This example uses two collections:此示例使用两个集合:

  • products, which contains documents describing the products that a shop sells,其中包含描述商店销售产品的文档
  • orders, which contains documents describing individual orders for products in a shop,其中包含描述商店中产品的单个订单的文档

An order can only contain one product. The aggregation uses a multi-field join to match a product document to documents representing orders of that product. 一个订单只能包含一个产品。聚合使用多字段联接将产品文档与表示该产品订单的文档相匹配。The aggregation joins collections by the name and variation fields in documents in the products collection, corresponding to the product_name and product_variation fields in documents in the orders collection.聚合通过products集合中文档中的namevariation字段连接集合,对应于orders集合中文档的product_nameproduct_variation字段。

To create the products and orders collections and insert the sample data, add the following code to your application:要创建productsorders集合并插入示例数据,请将以下代码添加到应用程序中:

MongoDatabase aggDB = mongoClient.getDatabase("agg_tutorials_db");
MongoCollection<Document> products = aggDB.getCollection("products");
MongoCollection<Document> orders = aggDB.getCollection("orders");

products.insertMany(
Arrays.asList(
new Document("name", "Asus Laptop")
.append("variation", "Ultra HD")
.append("category", "ELECTRONICS")
.append("description", "Great for watching movies"),

new Document("name", "Asus Laptop")
.append("variation", "Standard Display")
.append("category", "ELECTRONICS")
.append("description", "Good value laptop for students"),

new Document("name", "The Day Of The Triffids")
.append("variation", "1st Edition")
.append("category", "BOOKS")
.append("description", "Classic post-apocalyptic novel"),

new Document("name", "The Day Of The Triffids")
.append("variation", "2nd Edition")
.append("category", "BOOKS")
.append("description", "Classic post-apocalyptic novel"),

new Document("name", "Morphy Richards Food Mixer")
.append("variation", "Deluxe")
.append("category", "KITCHENWARE")
.append("description", "Luxury mixer turning good cakes into great")
)
);

orders.insertMany(
Arrays.asList(
new Document("customer_id", "elise_smith@myemail.com")
.append("orderdate", LocalDateTime.parse("2020-05-30T08:35:52"))
.append("product_name", "Asus Laptop")
.append("product_variation", "Standard Display")
.append("value", 431.43),

new Document("customer_id", "tj@wheresmyemail.com")
.append("orderdate", LocalDateTime.parse("2019-05-28T19:13:32"))
.append("product_name", "The Day Of The Triffids")
.append("product_variation", "2nd Edition")
.append("value", 5.01),

new Document("customer_id", "oranieri@warmmail.com")
.append("orderdate", LocalDateTime.parse("2020-01-01T08:25:37"))
.append("product_name", "Morphy Richards Food Mixer")
.append("product_variation", "Deluxe")
.append("value", 63.13),

new Document("customer_id", "jjones@tepidmail.com")
.append("orderdate", LocalDateTime.parse("2020-12-26T08:55:46"))
.append("product_name", "Asus Laptop")
.append("product_variation", "Standard Display")
.append("value", 429.65)
)
);
Kotlin(Coroutine)

Create the Template App创建模板应用程序

Before you begin following an aggregation tutorial, you must set up a new Java app. You can use this app to connect to a MongoDB deployment, insert sample data into MongoDB, and run the aggregation pipeline.在开始学习聚合教程之前,您必须设置一个新的Java应用程序。您可以使用此应用程序连接到MongoDB部署,将示例数据插入MongoDB,并运行聚合管道。

Tip

To learn how to install the driver and connect to MongoDB, see the Get Started with the Java Driver guide.要了解如何安装驱动程序并连接到MongoDB,请参阅Java驱动程序入门指南

To learn more about performing aggregations in the Java Sync Driver, see the Aggregation guide.要了解有关在Java同步驱动程序中执行聚合的更多信息,请参阅聚合指南

After you install the driver, create a file called AggTutorial.java. Paste the following code in this file to create an app template for the aggregation tutorials.安装驱动程序后,创建一个名为AggTutorial.java的文件。将以下代码粘贴到此文件中,为聚合教程创建应用程序模板。

Important

In the following code, read the code comments to find the sections of the code that you must modify for the tutorial you are following.在下面的代码中,阅读代码注释,找到您必须为正在学习的教程修改的代码部分。

If you attempt to run the code without making any changes, you will encounter a connection error.如果您尝试在不进行任何更改的情况下运行代码,您将遇到连接错误。

package org.example;

// Modify imports for each tutorial as needed.
import com.mongodb.client.*;
import com.mongodb.client.model.Accumulators;
import com.mongodb.client.model.Aggregates;
import com.mongodb.client.model.Field;
import com.mongodb.client.model.Filters;
import com.mongodb.client.model.Sorts;
import com.mongodb.client.model.Variable;
import org.bson.Document;
import org.bson.conversions.Bson;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class AggTutorial {
public static void main(String[] args) {
// Replace the placeholder with your connection string.
String uri = "<connection string>";

try (MongoClient mongoClient = MongoClients.create(uri)) {
MongoDatabase aggDB = mongoClient.getDatabase("agg_tutorials_db");

// Get a reference to relevant collections.
// ... MongoCollection<Document> someColl = ...
// ... MongoCollection<Document> anotherColl = ...

// Insert sample data into the collection or collections.
// ... someColl.insertMany(...);

// Create an empty pipeline array.
List<Bson> pipeline = new ArrayList<>();

// Add code to create pipeline stages.
// ... pipeline.add(...);

// Run the aggregation.
// ... AggregateIterable<Document> aggregationResult =
// someColl.aggregate(pipeline);

// Print the aggregation results.
for (Document document : aggregationResult) {
System.out.println(document.toJson());
}
}
}
}

For every tutorial, you must replace the connection string placeholder with your deployment's connection string.对于每个教程,您必须将连接字符串占位符替换为部署的连接字符串。

Tip

To learn how to locate your deployment's connection string, see the Create a Connection String step of the Java Sync Quick Start guide.要了解如何定位部署的连接字符串,请参阅《Java Sync快速入门》指南的创建连接字符串步骤。

For example, if your connection string is "mongodb+srv://mongodb-example:27017", your connection string assignment resembles the following:例如,如果连接字符串是"mongodb+srv://mongodb-example:27017",连接字符串分配类似于以下内容:

String uri = "mongodb+srv://mongodb-example:27017";

Create the Collection创建集合

This example uses two collections:此示例使用两个集合:

  • products, which contains documents describing the products that a shop sells,其中包含描述商店销售产品的文档
  • orders, which contains documents describing individual orders for products in a shop,其中包含描述商店中产品的单个订单的文档

An order can only contain one product. The aggregation uses a multi-field join to match a product document to documents representing orders of that product. 一个订单只能包含一个产品。聚合使用多字段联接将产品文档与表示该产品订单的文档相匹配。The aggregation joins collections by the name and variation fields in documents in the products collection, corresponding to the product_name and product_variation fields in documents in the orders collection.聚合通过products集合中文档中的namevariation(变体)字段连接集合,对应于orders集合中文档的product_nameproduct_variation字段。

First, create Kotlin data classes to model the data in the products and orders collections:首先,创建Kotlin数据类来对productsorders集合中的数据进行建模:

@Serializable
data class Product(
val name: String,
val variation: String,
val category: String,
val description: String
)

@Serializable
data class Order(
val customerID: String,
@Contextual val orderDate: LocalDateTime,
val productName: String,
val productVariation: String,
val value: Double
)

To create the products and orders collections and insert the sample data, add the following code to your application:要创建productsorders集合并插入示例数据,请将以下代码添加到应用程序中:

val products = aggDB.getCollection<Product>("products")
val orders = aggDB.getCollection<Order>("orders")

products.deleteMany(Filters.empty());
orders.deleteMany(Filters.empty());

products.insertMany(
listOf(
Product("Asus Laptop", "Ultra HD", "ELECTRONICS", "Great for watching movies"),
Product("Asus Laptop", "Standard Display", "ELECTRONICS", "Good value laptop for students"),
Product("The Day Of The Triffids", "1st Edition", "BOOKS", "Classic post-apocalyptic novel"),
Product("The Day Of The Triffids", "2nd Edition", "BOOKS", "Classic post-apocalyptic novel"),
Product(
"Morphy Richards Food Mixer",
"Deluxe",
"KITCHENWARE",
"Luxury mixer turning good cakes into great"
)
)
)

orders.insertMany(
listOf(
Order(
"elise_smith@myemail.com",
LocalDateTime.parse("2020-05-30T08:35:52"),
"Asus Laptop",
"Standard Display",
431.43
),
Order(
"tj@wheresmyemail.com",
LocalDateTime.parse("2019-05-28T19:13:32"),
"The Day Of The Triffids",
"2nd Edition",
5.01
),
Order(
"oranieri@warmmail.com",
LocalDateTime.parse("2020-01-01T08:25:37"),
"Morphy Richards Food Mixer",
"Deluxe",
63.13
),
Order(
"jjones@tepidmail.com",
LocalDateTime.parse("2020-12-26T08:55:46"),
"Asus Laptop",
"Standard Display",
429.65
)
)
)
Node.js

Create the Template App创建模板应用程序

Before you begin following this aggregation tutorial, you must set up a new Node.js app. You can use this app to connect to a MongoDB deployment, insert sample data into MongoDB, and run the aggregation pipeline.在开始学习本聚合教程之前,您必须设置一个新的Node.js应用程序。您可以使用此应用程序连接到MongoDB部署,将示例数据插入MongoDB,并运行聚合管道。

Tip

To learn how to install the driver and connect to MongoDB, see the Node.js Driver Quick Start guide.要了解如何安装驱动程序并连接到MongoDB,请参阅Node.js驱动程序快速入门指南

To learn more about performing aggregations in the Node.js Driver, see the Aggregation guide.要了解有关在Node.js驱动程序中执行聚合的更多信息,请参阅聚合指南

After you install the driver, create a file to run the tutorial template. Paste the following code in this file to create an app template for the aggregation tutorials.安装驱动程序后,创建一个文件来运行教程模板。将以下代码粘贴到此文件中,为聚合教程创建应用程序模板。

Important

In the following code, read the code comments to find the sections of the code that you must modify for the tutorial you are following.在下面的代码中,阅读代码注释,找到您必须为正在学习的教程修改的代码部分。

If you attempt to run the code without making any changes, you will encounter a connection error.如果您尝试在不进行任何更改的情况下运行代码,您将遇到连接错误。

const { MongoClient } = require('mongodb');
// Replace the placeholder with your connection string.
const uri = '<connection-string>';
const client = new MongoClient(uri);
export async function run() {
try {
const aggDB = client.db('agg_tutorials_db');

// Get a reference to relevant collections.
// ... const someColl =
// ... const anotherColl =

// Delete any existing documents in collections.
// ... await someColl.deleteMany({});

// Insert sample data into the collection or collections.
// ... const someData = [ ... ];
// ... await someColl.insertMany(someData);

// Create an empty pipeline array.
const pipeline = [];

// Add code to create pipeline stages.
// ... pipeline.push({ ... })

// Run the aggregation.
// ... const aggregationResult = ...

// Print the aggregation results.
for await (const document of aggregationResult) {
console.log(document);
}
} finally {
await client.close();
}
}

run().catch(console.dir);

For every tutorial, you must replace the connection string placeholder with your deployment's connection string.对于每个教程,您必须将连接字符串占位符替换为部署的连接字符串。

Tip

To learn how to locate your deployment's connection string, see the Create a Connection String step of the Node.js Quick Start guide.要了解如何定位部署的连接字符串,请参阅Node.js快速入门指南的创建连接字符串步骤。

For example, if your connection string is "mongodb+srv://mongodb-example:27017", your connection string assignment resembles the following:例如,如果连接字符串是"mongodb+srv://mongodb-example:27017",连接字符串分配类似于以下内容:

const uri = "mongodb+srv://mongodb-example:27017";

Create the Collection创建集合

This example uses two collections:此示例使用两个集合:

  • products, which contains documents describing the products that a shop sells,其中包含描述商店销售产品的文档
  • orders, which contains documents describing individual orders for products in a shop,其中包含描述商店中产品的单个订单的文档

An order can only contain one product. The aggregation uses a multi-field join to match a product document to documents representing orders of that product. The aggregation joins collections by the name and variation fields in documents in the products collection, corresponding to the product_name and product_variation fields in documents in the orders collection.一个订单只能包含一个产品。聚合使用多字段联接将产品文档与表示该产品订单的文档相匹配。聚合通过products集合中文档中的namevariation(变体)字段连接集合,对应于orders集合中文档的product_nameproduct_variation字段。

To create the products and orders collections and insert the sample data, add the following code to your application:要创建productsorders集合并插入示例数据,请将以下代码添加到应用程序中:

const products = aggDB.collection('products');
const orders = aggDB.collection('orders');

await products.insertMany([
{
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 orders.insertMany([
{
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,
},
]);
PHP

Create the Template App创建模板应用程序

Before you begin following this aggregation tutorial, you must set up a new Go app. You can use this app to connect to a MongoDB deployment, insert sample data into MongoDB, and run the aggregation pipeline.在开始学习此聚合教程之前,您必须设置一个新的Go应用程序。您可以使用此应用程序连接到MongoDB部署,将示例数据插入MongoDB,并运行聚合管道。

Tip

To learn how to install the driver and connect to MongoDB, see the Go Driver Quick Start guide.要了解如何安装驱动程序并连接到MongoDB,请参阅Go驱动程序快速入门指南

To learn more about performing aggregations in the Go Driver, see the Aggregation guide.要了解有关在Go驱动程序中执行聚合的更多信息,请参阅聚合指南

After you install the driver, create a file called agg_tutorial.go. Paste the following code in this file to create an app template for the aggregation tutorials.安装驱动程序后,创建一个名为agg_tutorial.go的文件。将以下代码粘贴到此文件中,为聚合教程创建应用程序模板。

Important

In the following code, read the code comments to find the sections of the code that you must modify for the tutorial you are following.在下面的代码中,阅读代码注释,找到您必须为正在学习的教程修改的代码部分。

If you attempt to run the code without making any changes, you will encounter a connection error.如果您尝试在不进行任何更改的情况下运行代码,您将遇到连接错误。

package main

import (
"context"
"fmt"
"log"

"go.mongodb.org/mongo-driver/v2/bson"
"go.mongodb.org/mongo-driver/v2/mongo"
"go.mongodb.org/mongo-driver/v2/mongo/options"
)

// Define structs.
// type MyStruct struct { ... }

func main() {
ctx := context.Background()
// Replace the placeholder with your connection string.
const uri = "<connection string>"

client, err := mongo.Connect(options.Client().ApplyURI(uri))
if err != nil {
log.Fatal(err)
}

defer func() {
if err = client.Disconnect(ctx); err != nil {
log.Fatal(err)
}
}()

aggDB := client.Database("agg_tutorials_db")

// Get a reference to relevant collections.
// ... someColl := aggDB.Collection("...")
// ... anotherColl := aggDB.Collection("...")

// Delete any existing documents in collections if needed.
// ... someColl.DeleteMany(cxt, bson.D{})

// Insert sample data into the collection or collections.
// ... _, err = someColl.InsertMany(...)

// Add code to create pipeline stages.
// ... myStage := bson.D{{...}}

// Create a pipeline that includes the stages.
// ... pipeline := mongo.Pipeline{...}

// Run the aggregation.
// ... cursor, err := someColl.Aggregate(ctx, pipeline)

if err != nil {
log.Fatal(err)
}

defer func() {
if err := cursor.Close(ctx); err != nil {
log.Fatalf("failed to close cursor: %v", err)
}
}()

// Decode the aggregation results.
var results []bson.D
if err = cursor.All(ctx, &results); err != nil {
log.Fatalf("failed to decode results: %v", err)
}

// Print the aggregation results.
for _, result := range results {
res, _ := bson.MarshalExtJSON(result, false, false)
fmt.Println(string(res))
}
}

For every tutorial, you must replace the connection string placeholder with your deployment's connection string.对于每个教程,您必须将连接字符串占位符替换为部署的连接字符串。

Tip

To learn how to locate your deployment's connection string, see the Create a MongoDB Cluster step of the Go Quick Start guide.要了解如何定位部署的连接字符串,请参阅Go快速入门指南的创建MongoDB集群步骤

For example, if your connection string is "mongodb+srv://mongodb-example:27017", your connection string assignment resembles the following:例如,如果连接字符串是"mongodb+srv://mongodb-example:27017",连接字符串分配类似于以下内容:

const uri = "mongodb+srv://mongodb-example:27017";

Create the Collection创建集合

This example uses two collections:此示例使用两个集合:

  • products, which contains documents describing the products that a shop sells,其中包含描述商店销售产品的文档
  • orders, which contains documents describing individual orders for products in a shop,其中包含描述商店中产品的单个订单的文档

An order can only contain one product. The aggregation uses a multi-field join to match a product document to documents representing orders of that product. 一个订单只能包含一个产品。聚合使用多字段联接将产品文档与表示该产品订单的文档相匹配。The aggregation joins collections by the name and variation fields in documents in the products collection, corresponding to the product_name and product_variation fields in documents in the orders collection.聚合通过products集合中文档中的namevariation(变体)字段连接集合,对应于orders集合中文档的product_nameproduct_variation字段。

To create the products and orders collections and insert the sample data, add the following code to your application:要创建productsorders集合并插入示例数据,请将以下代码添加到应用程序中:

$products = $client->agg_tutorials_db->products;
$orders = $client->agg_tutorials_db->orders;

$products->deleteMany([]);
$orders->deleteMany([]);

$products->insertMany(
[
[
'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"
]
]
);

$orders->insertMany(
[
[
'customer_id' => "elise_smith@myemail.com",
'orderdate' => new UTCDateTime((new DateTimeImmutable("2020-05-30T08:35:52"))),
'product_name' => "Asus Laptop",
'product_variation' => "Standard Display",
'value' => 431.43
],
[
'customer_id' => "tj@wheresmyemail.com",
'orderdate' => new UTCDateTime((new DateTimeImmutable("2019-05-28T19:13:32"))),
'product_name' => "The Day Of The Triffids",
'product_variation' => "2nd Edition",
'value' => 5.01
],
[
'customer_id' => "oranieri@warmmail.com",
'orderdate' => new UTCDateTime((new DateTimeImmutable("2020-01-01T08:25:37"))),
'product_name' => "Morphy Richards Food Mixer",
'product_variation' => "Deluxe",
'value' => 63.13
],
[
'customer_id' => "jjones@tepidmail.com",
'orderdate' => new UTCDateTime((new DateTimeImmutable("2020-12-26T08:55:46"))),
'product_name' => "Asus Laptop",
'product_variation' => "Standard Display",
'value' => 429.65
]
]
);
Python

Create the Template App创建模板应用程序

Before you begin following this aggregation tutorial, you must set up a new Python app. You can use this app to connect to a MongoDB deployment, insert sample data into MongoDB, and run the aggregation pipeline.在开始学习本聚合教程之前,您必须设置一个新的Python应用程序。您可以使用此应用程序连接到MongoDB部署,将示例数据插入MongoDB,并运行聚合管道。

Tip

To learn how to install PyMongo and connect to MongoDB, see the Get Started with PyMongo tutorial.要了解如何安装PyMongo并连接到MongoDB,请参阅PyMongo入门教程

To learn more about performing aggregations in PyMongo, see the Aggregation guide.要了解有关在PyMongo中执行聚合的更多信息,请参阅聚合指南

After you install the library, create a file called agg_tutorial.py. Paste the following code in this file to create an app template for the aggregation tutorials.安装库后,创建一个名为agg_tutorial.py的文件。将以下代码粘贴到此文件中,为聚合教程创建应用程序模板。

Important

In the following code, read the code comments to find the sections of the code that you must modify for the tutorial you are following.在下面的代码中,阅读代码注释,找到您必须为正在学习的教程修改的代码部分。

If you attempt to run the code without making any changes, you will encounter a connection error.如果您尝试在不进行任何更改的情况下运行代码,您将遇到连接错误。

# Modify imports for each tutorial as needed.
from pymongo import MongoClient

# Replace the placeholder with your connection string.
uri = "<connection-string>"
client = MongoClient(uri)

try:
agg_db = client["agg_tutorials_db"]

# Get a reference to relevant collections.
# ... some_coll = agg_db["some_coll"]
# ... another_coll = agg_db["another_coll"]

# Delete any existing documents in collections if needed.
# ... some_coll.delete_many({})

# Insert sample data into the collection or collections.
# ... some_coll.insert_many(...)

# Create an empty pipeline array.
pipeline = []

# Add code to create pipeline stages.
# ... pipeline.append({...})

# Run the aggregation.
# ... aggregation_result = ...

# Print the aggregation results.
for document in aggregation_result:
print(document)

finally:
client.close()

For every tutorial, you must replace the connection string placeholder with your deployment's connection string.对于每个教程,您必须将连接字符串占位符替换为部署的连接字符串。

Tip

To learn how to locate your deployment's connection string, see the Create a Connection String step of the Get Started with the PHP Library tutorial.要了解如何定位部署的连接字符串,请参阅PHP库入门教程的创建连接字符串步骤。

For example, if your connection string is "mongodb+srv://mongodb-example:27017", your connection string assignment resembles the following:例如,如果连接字符串是"mongodb+srv://mongodb-example:27017",连接字符串分配类似于以下内容:

uri = "mongodb+srv://mongodb-example:27017"

Create the Collection创建集合

This example uses two collections:此示例使用两个集合:

  • products, which contains documents describing the products that a shop sells,其中包含描述商店销售产品的文档
  • orders, which contains documents describing individual orders for products in a shop,其中包含描述商店中产品的单个订单的文档

An order can only contain one product. The aggregation uses a multi-field join to match a product document to documents representing orders of that product. 一个订单只能包含一个产品。聚合使用多字段联接将产品文档与表示该产品订单的文档相匹配。The aggregation joins collections by the name and variation fields in documents in the products collection, corresponding to the product_name and product_variation fields in documents in the orders collection.聚合通过products集合中文档中的namevariation(变体)字段连接集合,对应于orders集合中文档的product_nameproduct_variation字段。

To create the products and orders collections and insert the sample data, add the following code to your application:要创建productsorders集合并插入示例数据,请将以下代码添加到应用程序中:

products_coll = agg_db["products"]
orders_coll = agg_db["orders"]

order_data = [
{
"customer_id": "elise_smith@myemail.com",
"orderdate": datetime(2020, 5, 30, 8, 35, 52),
"product_name": "Asus Laptop",
"product_variation": "Standard Display",
"value": 431.43,
},
{
"customer_id": "tj@wheresmyemail.com",
"orderdate": datetime(2019, 5, 28, 19, 13, 32),
"product_name": "The Day Of The Triffids",
"product_variation": "2nd Edition",
"value": 5.01,
},
{
"customer_id": "oranieri@warmmail.com",
"orderdate": datetime(2020, 1, 1, 8, 25, 37),
"product_name": "Morphy Richards Food Mixer",
"product_variation": "Deluxe",
"value": 63.13,
},
{
"customer_id": "jjones@tepidmail.com",
"orderdate": datetime(2020, 12, 26, 8, 55, 46),
"product_name": "Asus Laptop",
"product_variation": "Standard Display",
"value": 429.65,
},
]

orders_coll.insert_many(order_data)

products_data = [
{
"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",
},
]

products_coll.insert_many(products_data)
Ruby

Create the Template App创建模板应用程序

Before you begin following this aggregation tutorial, you must set up a new Ruby app. You can use this app to connect to a MongoDB deployment, insert sample data into MongoDB, and run the aggregation pipeline.在开始学习本聚合教程之前,您必须设置一个新的Ruby应用程序。您可以使用此应用程序连接到MongoDB部署,将示例数据插入MongoDB,并运行聚合管道。

Tip

To learn how to install the Ruby Driver and connect to MongoDB, see the Get Started with the Ruby Driver guide.要了解如何安装Ruby驱动程序并连接到MongoDB,请参阅Ruby驱动程序入门指南

To learn more about performing aggregations in the Ruby Driver, see the Aggregation guide.要了解有关在Ruby驱动程序中执行聚合的更多信息,请参阅聚合指南

After you install the driver, create a file called agg_tutorial.rb. Paste the following code in this file to create an app template for the aggregation tutorials.安装驱动程序后,创建一个名为agg_tutorial.rb的文件。将以下代码粘贴到此文件中,为聚合教程创建应用程序模板。

Important

In the following code, read the code comments to find the sections of the code that you must modify for the tutorial you are following.在下面的代码中,阅读代码注释,找到您必须为正在学习的教程修改的代码部分。

If you attempt to run the code without making any changes, you will encounter a connection error.如果您尝试在不进行任何更改的情况下运行代码,您将遇到连接错误。

# typed: strict
require 'mongo'
require 'bson'

# Replace the placeholder with your connection string.
uri = "<connection string>"

Mongo::Client.new(uri) do |client|

agg_db = client.use('agg_tutorials_db')

# Get a reference to relevant collections.
# ... some_coll = agg_db[:some_coll]

# Delete any existing documents in collections if needed.
# ... some_coll.delete_many({})

# Insert sample data into the collection or collections.
# ... some_coll.insert_many( ... )

# Add code to create pipeline stages within the array.
# ... pipeline = [ ... ]

# Run the aggregation.
# ... aggregation_result = some_coll.aggregate(pipeline)

# Print the aggregation results.
aggregation_result.each do |doc|
puts doc
end

end

For every tutorial, you must replace the connection string placeholder with your deployment's connection string.对于每个教程,您必须将连接字符串占位符替换为部署的连接字符串。

Tip

To learn how to locate your deployment's connection string, see the Create a Connection String step of the Ruby Get Started guide.要了解如何定位部署的连接字符串,请参阅Ruby入门指南的创建连接字符串步骤。

For example, if your connection string is "mongodb+srv://mongodb-example:27017", your connection string assignment resembles the following:例如,如果连接字符串是"mongodb+srv://mongodb-example:27017",连接字符串分配类似于以下内容:

uri = "mongodb+srv://mongodb-example:27017"

Create the Collection创建集合

This example uses two collections:此示例使用两个集合:

  • products, which contains documents describing the products that a shop sells,其中包含描述商店销售产品的文档
  • orders, which contains documents describing individual orders for products in a shop,其中包含描述商店中产品的单个订单的文档

An order can only contain one product. The aggregation uses a multi-field join to match a product document to documents representing orders of that product. 一个订单只能包含一个产品。聚合使用多字段联接将产品文档与表示该产品订单的文档相匹配。The aggregation joins collections by the name and variation fields in documents in the products collection, corresponding to the product_name and product_variation fields in documents in the orders collection.聚合通过products集合中文档中的namevariation(变体)字段连接集合,对应于orders集合中文档的product_nameproduct_variation字段。

To create the products and orders collections and insert the sample data, add the following code to your application:要创建productsorders集合并插入示例数据,请将以下代码添加到应用程序中:

products = agg_db[:products]
orders = agg_db[:orders]

products.delete_many({})
orders.delete_many({})

products.insert_many(
[
{
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",
},
]
)

orders.insert_many(
[
{
customer_id: "elise_smith@myemail.com",
orderdate: DateTime.parse("2020-05-30T08:35:52Z"),
product_name: "Asus Laptop",
product_variation: "Standard Display",
value: 431.43,
},
{
customer_id: "tj@wheresmyemail.com",
orderdate: DateTime.parse("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: DateTime.parse("2020-01-01T08:25:37Z"),
product_name: "Morphy Richards Food Mixer",
product_variation: "Deluxe",
value: 63.13,
},
{
customer_id: "jjones@tepidmail.com",
orderdate: DateTime.parse("2020-12-26T08:55:46Z"),
product_name: "Asus Laptop",
product_variation: "Standard Display",
value: 429.65,
},
]
)
Rust

Create the Template App创建模板应用程序

Before you begin following this aggregation tutorial, you must set up a new Rust app. You can use this app to connect to a MongoDB deployment, insert sample data into MongoDB, and run the aggregation pipeline.在开始学习本聚合教程之前,您必须设置一个新的Rust应用程序。您可以使用此应用程序连接到MongoDB部署,将示例数据插入MongoDB,并运行聚合管道。

Tip

To learn how to install the driver and connect to MongoDB, see the Rust Driver Quick Start guide.要了解如何安装驱动程序并连接到MongoDB,请参阅Rust驱动程序快速入门指南

To learn more about performing aggregations in the Rust Driver, see the Aggregation guide.要了解有关在Rust驱动程序中执行聚合的更多信息,请参阅聚合指南

After you install the driver, create a file called agg-tutorial.rs. Paste the following code in this file to create an app template for the aggregation tutorials.安装驱动程序后,创建一个名为agg-tutorial.rs的文件。将以下代码粘贴到此文件中,为聚合教程创建应用程序模板。

Important

In the following code, read the code comments to find the sections of the code that you must modify for the tutorial you are following.在下面的代码中,阅读代码注释,找到您必须为正在学习的教程修改的代码部分。

If you attempt to run the code without making any changes, you will encounter a connection error.如果您尝试在不进行任何更改的情况下运行代码,您将遇到连接错误。

use mongodb::{
bson::{doc, Document},
options::ClientOptions,
Client,
};
use futures::stream::TryStreamExt;
use std::error::Error;

// Define structs.
// #[derive(Debug, Serialize, Deserialize)]
// struct MyStruct { ... }

#[tokio::main]
async fn main() mongodb::error::Result<()> {
// Replace the placeholder with your connection string.
let uri = "<connection string>";
let client = Client::with_uri_str(uri).await?;

let agg_db = client.database("agg_tutorials_db");

// Get a reference to relevant collections.
// ... let some_coll: Collection<T> = agg_db.collection("...");
// ... let another_coll: Collection<T> = agg_db.collection("...");

// Delete any existing documents in collections if needed.
// ... some_coll.delete_many(doc! {}).await?;

// Insert sample data into the collection or collections.
// ... some_coll.insert_many(vec![...]).await?;

// Create an empty pipeline.
let mut pipeline = Vec::new();

// Add code to create pipeline stages.
// pipeline.push(doc! { ... });

// Run the aggregation and print the results.
let mut results = some_coll.aggregate(pipeline).await?;
while let Some(result) = results.try_next().await? {
println!("{:?}\n", result);
}
Ok(())
}

For every tutorial, you must replace the connection string placeholder with your deployment's connection string.对于每个教程,您必须将连接字符串占位符替换为部署的连接字符串。

Tip

To learn how to locate your deployment's connection string, see the Create a Connection String step of the Rust Quick Start guide.要了解如何定位部署的连接字符串,请参阅Rust快速入门指南的创建连接字符串步骤。

For example, if your connection string is "mongodb+srv://mongodb-example:27017", your connection string assignment resembles the following:例如,如果连接字符串是"mongodb+srv://mongodb-example:27017",连接字符串分配类似于以下内容:

let uri = "mongodb+srv://mongodb-example:27017";

Create the Collection创建集合

This example uses two collections:此示例使用两个集合:

  • products, which contains documents describing the products that a shop sells,其中包含描述商店销售产品的文档
  • orders, which contains documents describing individual orders for products in a shop,其中包含描述商店中产品的单个订单的文档

An order can only contain one product. The aggregation uses a multi-field join to match a product document to documents representing orders of that product. 一个订单只能包含一个产品。聚合使用多字段联接将产品文档与表示该产品订单的文档相匹配。The aggregation joins collections by the name and variation fields in documents in the products collection, corresponding to the product_name and product_variation fields in documents in the orders collection.聚合通过products集合中文档中的namevariation(变体)字段连接集合,对应于orders集合中文档的product_nameproduct_variation字段。

First, create Rust structs to model the data in the products and orders collections:首先,创建Rust结构体来对productsorders集合中的数据进行建模:

#[derive(Debug, Serialize, Deserialize)]
struct Product {
name: String,
variation: String,
category: String,
description: String,
}

#[derive(Debug, Serialize, Deserialize)]
struct Order {
customer_id: String,
order_date: DateTime,
product_name: String,
product_variation: String,
value: f32,
}

To create the products and orders collections and insert the sample data, add the following code to your application:要创建productsorders集合并插入示例数据,请将以下代码添加到应用程序中:

let products: Collection<Product> = agg_db.collection("products");
let orders: Collection<Order> = agg_db.collection("orders");

products.delete_many(doc! {}).await?;
orders.delete_many(doc! {}).await?;

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

let order_docs = vec![
Order {
customer_id: "elise_smith@myemail.com".to_string(),
order_date: DateTime::builder().year(2020).month(5).day(30).hour(8).minute(35).second(52).build().unwrap(),
product_name: "Asus Laptop".to_string(),
product_variation: "Standard Display".to_string(),
value: 431.43,
},
Order {
customer_id: "tj@wheresmyemail.com".to_string(),
order_date: DateTime::builder().year(2019).month(5).day(28).hour(19).minute(13).second(32).build().unwrap(),
product_name: "The Day Of The Triffids".to_string(),
product_variation: "2nd Edition".to_string(),
value: 5.01,
},
Order {
customer_id: "oranieri@warmmail.com".to_string(),
order_date: DateTime::builder().year(2020).month(1).day(1).hour(8).minute(25).second(37).build().unwrap(),
product_name: "Morphy Richards Food Mixer".to_string(),
product_variation: "Deluxe".to_string(),
value: 63.13,
},
Order {
customer_id: "jjones@tepidmail.com".to_string(),
order_date: DateTime::builder().year(2020).month(12).day(26).hour(8).minute(55).second(46).build().unwrap(),
product_name: "Asus Laptop".to_string(),
product_variation: "Standard Display".to_string(),
value: 429.65,
},
];
orders.insert_many(order_docs).await?;
scala

Create the Template App创建模板应用程序

Before you begin following an aggregation tutorial, you must set up a new Scala app. You can use this app to connect to a MongoDB deployment, insert sample data into MongoDB, and run the aggregation pipeline.在开始学习聚合教程之前,您必须设置一个新的Scala应用程序。您可以使用此应用程序连接到MongoDB部署,将示例数据插入MongoDB,并运行聚合管道。

Tip

To learn how to install the driver and connect to MongoDB, see the Get Started with the Scala Driver guide.要了解如何安装驱动程序并连接到MongoDB,请参阅Scala驱动程序入门指南。

To learn more about performing aggregations in the Scala Driver, see the Aggregation guide.要了解有关在Scala驱动程序中执行聚合的更多信息,请参阅聚合指南

After you install the driver, create a file called AggTutorial.scala. Paste the following code in this file to create an app template for the aggregation tutorials.安装驱动程序后,创建一个名为AggTutorial.scala的文件。将以下代码粘贴到此文件中,为聚合教程创建应用程序模板。

Important

In the following code, read the code comments to find the sections of the code that you must modify for the tutorial you are following.在下面的代码中,阅读代码注释,找到您必须为正在学习的教程修改的代码部分。

If you attempt to run the code without making any changes, you will encounter a connection error.如果您尝试在不进行任何更改的情况下运行代码,您将遇到连接错误。

package org.example;

// Modify imports for each tutorial as needed.
import org.mongodb.scala.MongoClient
import org.mongodb.scala.bson.Document
import org.mongodb.scala.model.{Accumulators, Aggregates, Field, Filters, Variable}

import java.text.SimpleDateFormat

object FilteredSubset {

def main(args: Array[String]): Unit = {

// Replace the placeholder with your connection string.
val uri = "<connection string>"
val mongoClient = MongoClient(uri)
Thread.sleep(1000)

val aggDB = mongoClient.getDatabase("agg_tutorials_db")

// Get a reference to relevant collections.
// ... val someColl = aggDB.getCollection("someColl")
// ... val anotherColl = aggDB.getCollection("anotherColl")

// Delete any existing documents in collections if needed.
// ... someColl.deleteMany(Filters.empty()).subscribe(...)

// If needed, create the date format template.
val dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss")

// Insert sample data into the collection or collections.
// ... someColl.insertMany(...).subscribe(...)

Thread.sleep(1000)

// Add code to create pipeline stages within the Seq.
// ... val pipeline = Seq(...)

// Run the aggregation and print the results.
// ... someColl.aggregate(pipeline).subscribe(...)

Thread.sleep(1000)
mongoClient.close()
}
}

For every tutorial, you must replace the connection string placeholder with your deployment's connection string.对于每个教程,您必须将连接字符串占位符替换为部署的连接字符串。

Tip

To learn how to locate your deployment's connection string, see the Create a Connection String step of the Scala Driver Get Started guide.要了解如何定位部署的连接字符串,请参阅《Scala驱动程序入门》指南的创建连接字符串步骤。

For example, if your connection string is "mongodb+srv://mongodb-example:27017", your connection string assignment resembles the following:例如,如果连接字符串是"mongodb+srv://mongodb-example:27017",连接字符串分配类似于以下内容:

val uri = "mongodb+srv://mongodb-example:27017"

Create the Collection创建集合

This example uses two collections:此示例使用两个集合:

  • products, which contains documents describing the products that a shop sells,其中包含描述商店销售产品的文档
  • orders, which contains documents describing individual orders for products in a shop,其中包含描述商店中产品的单个订单的文档

An order can only contain one product. The aggregation uses a multi-field join to match a product document to documents representing orders of that product. 一个订单只能包含一个产品。聚合使用多字段联接将产品文档与表示该产品订单的文档相匹配。The aggregation joins collections by the name and variation fields in documents in the products collection, corresponding to the product_name and product_variation fields in documents in the orders collection.聚合通过产品集合中文档中的namevariation(变体)字段连接集合,对应于orders集合中文档的product_nameproduct_variation字段。

To create the products and orders collections and insert the sample data, add the following code to your application:要创建productsorders集合并插入示例数据,请将以下代码添加到应用程序中:

val products = aggDB.getCollection("products")
val orders = aggDB.getCollection("orders")

products.deleteMany(Filters.empty()).subscribe(
_ => {},
e => println("Error: " + e.getMessage),
)

orders.deleteMany(Filters.empty()).subscribe(
_ => {},
e => println("Error: " + e.getMessage),
)

val dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss")

products.insertMany(
Seq(
Document(
"name" -> "Asus Laptop",
"variation" -> "Ultra HD",
"category" -> "ELECTRONICS",
"description" -> "Great for watching movies"
),
Document(
"name" -> "Asus Laptop",
"variation" -> "Standard Display",
"category" -> "ELECTRONICS",
"description" -> "Good value laptop for students"
),
Document(
"name" -> "The Day Of The Triffids",
"variation" -> "1st Edition",
"category" -> "BOOKS",
"description" -> "Classic post-apocalyptic novel"
),
Document(
"name" -> "The Day Of The Triffids",
"variation" -> "2nd Edition",
"category" -> "BOOKS",
"description" -> "Classic post-apocalyptic novel"
),
Document(
"name" -> "Morphy Richards Food Mixer",
"variation" -> "Deluxe",
"category" -> "KITCHENWARE",
"description" -> "Luxury mixer turning good cakes into great"
)
)
).subscribe(
_ => {},
e => println("Error: " + e.getMessage),
)

orders.insertMany(
Seq(
Document(
"customer_id" -> "elise_smith@myemail.com",
"orderdate" -> dateFormat.parse("2020-05-30T08:35:52"),
"product_name" -> "Asus Laptop",
"product_variation" -> "Standard Display",
"value" -> 431.43
),
Document(
"customer_id" -> "tj@wheresmyemail.com",
"orderdate" -> dateFormat.parse("2019-05-28T19:13:32"),
"product_name" -> "The Day Of The Triffids",
"product_variation" -> "2nd Edition",
"value" -> 5.01
),
Document(
"customer_id" -> "oranieri@warmmail.com",
"orderdate" -> dateFormat.parse("2020-01-01T08:25:37"),
"product_name" -> "Morphy Richards Food Mixer",
"product_variation" -> "Deluxe",
"value" -> 63.13
),
Document(
"customer_id" -> "jjones@tepidmail.com",
"orderdate" -> dateFormat.parse("2020-12-26T08:55:46"),
"product_name" -> "Asus Laptop",
"product_variation" -> "Standard Display",
"value" -> 429.65
)
)
).subscribe(
_ => {},
e => println("Error: " + e.getMessage),
)

Steps步骤

The following steps demonstrate how to create and run an aggregation pipeline to join collections on multiple fields.以下步骤演示了如何创建和运行聚合管道以连接多个字段上的集合。

MongoDB Shell
1

Create an embedded pipeline to use in the lookup stage.创建在查找阶段使用的嵌入式管道。

The first stage of the pipeline is a $lookup stage to join the orders collection to the products collection by two fields in each collection. The $lookup stage contains an embedded pipeline to configure the join.管道的第一阶段是$lookup阶段,通过每个集合中的两个字段将orders集合连接到products集合。$lookup阶段包含一个用于配置连接的嵌入式管道。

embedded_pl = [
// Stage 1: Match the values of two fields on each side of the join
// The $eq filter uses aliases for the name and variation fields set
{ $match: {
$expr: {
$and: [
{ $eq: ["$product_name", "$$prdname"] },
{ $eq: ["$product_variation", "$$prdvartn"] }
]
}
} },

// Stage 2: Match orders placed in 2020
{ $match: {
orderdate: {
$gte: new Date("2020-01-01T00:00:00Z"),
$lt: new Date("2021-01-01T00:00:00Z")
}
} },

// Stage 3: Remove unneeded fields from the orders collection side of the join
{ $unset: ["_id", "product_name", "product_variation"] }
]
2

Run the aggregation pipeline.运行聚合管道。

db.products.aggregate( [
// Use the embedded pipeline in a lookup stage
{ $lookup: {
from: "orders",
let: {
prdname: "$name",
prdvartn: "$variation"
},
pipeline: embedded_pl,
as: "orders"
} },

// Match products ordered in 2020
{ $match: { orders: { $ne: [] } } },

// Remove unneeded fields
{ $unset: ["_id", "description"] }
] )
3

Interpret the aggregation results.解释聚合结果。

The aggregated results contain two documents. The documents represent products ordered 2020. Each document contains an orders array field that lists details about each order for that product.汇总结果包含两个文档。这些文件代表了2020年订购的产品。每个文档都包含一个orders数组字段,其中列出了该产品的每个订单的详细信息。

{
name: 'Asus Laptop',
variation: 'Standard Display',
category: 'ELECTRONICS',
orders: [
{
customer_id: 'elise_smith@myemail.com',
orderdate: ISODate('2020-05-30T08:35:52.000Z'),
value: 431.43
},
{
customer_id: 'jjones@tepidmail.com',
orderdate: ISODate('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: ISODate('2020-01-01T08:25:37.000Z'),
value: 63.13
}
]
}
C
1

Add a lookup stage to link the collections and import fields.添加查找阶段以链接集合和导入字段。

The first stage of the pipeline is a $lookup stage to join the orders collection to the products collection by two fields in each collection. The lookup stage contains an embedded pipeline to configure the join.管道的第一阶段是$lookup阶段,通过每个集合中的两个字段将orders集合连接到products集合。查找阶段包含一个用于配置连接的嵌入式管道。

Create the embedded pipeline, then add a $match stage to match the values of two fields on each side of the join. Note that the following code uses aliases for the name and variation fields set when creating the $lookup stage:创建嵌入式管道,然后添加一个$match阶段,以匹配连接两侧两个字段的值。请注意,以下代码在创建$lookup阶段时为namevariation字段设置了别名:

bson_t embedded_pipeline;
bson_array_builder_t *bab = bson_array_builder_new();

bson_array_builder_append_document(bab, BCON_NEW(
"$match", "{",
"$expr", "{", "$and",
"[",
"{", "$eq", "[", BCON_UTF8("$product_name"), BCON_UTF8("$$prdname"), "]", "}",
"{", "$eq", "[", BCON_UTF8("$product_variation"), BCON_UTF8("$$prdvartn"), "]", "}",
"]",
"}",
"}"));

Within the embedded pipeline, add another $match stage to match orders placed in 2020:在嵌入式管道中,添加另一个$match阶段来匹配2020年的订单:

bson_array_builder_append_document(bab, BCON_NEW(
"$match", "{", "orderdate",
"{",
"$gte", BCON_DATE_TIME(1577836800000UL),
"$lt", BCON_DATE_TIME(1609459200000UL),
"}",
"}"));

Within the embedded pipeline, add an $unset stage to remove unneeded fields from the orders collection side of the join:在嵌入式管道中,添加一个$unset阶段,从连接的orders集合端删除不需要的字段:

bson_array_builder_append_document(bab, BCON_NEW(
"$unset",
"[", BCON_UTF8("_id"), BCON_UTF8("product_name"), BCON_UTF8("product_variation"),
"]"));

// Builds the embedded pipeline array and cleans up resources
bson_array_builder_build(bab, &embedded_pipeline);
bson_array_builder_destroy(bab);

After the embedded pipeline is completed, add the $lookup stage to the main aggregation pipeline. Configure this stage to store the processed lookup fields in an array field called orders:嵌入式管道完成后,将$lookup阶段添加到主聚合管道中。配置此阶段以将处理后的查找字段存储在名为orders的数组字段中:

"{", "$lookup", "{",
"from", BCON_UTF8("orders"),
"let", "{",
"prdname", BCON_UTF8("$name"),
"prdvartn", BCON_UTF8("$variation"),
"}",
"pipeline", BCON_ARRAY(&embedded_pipeline),
"as", BCON_UTF8("orders"),
"}", "}",
2

Add a match stage for products ordered in 2020.为2020年订购的产品添加匹配阶段。

Next, add a $match stage to only show products for which there is at least one order in 2020, based on the orders array calculated in the previous step:接下来,根据上一步计算的orders数组,添加一个$match阶段,仅显示2020年至少有一个订单的产品:

"{",
"$match", "{",
"orders", "{", "$ne", "[", "]", "}",
"}", "}",
3

Add an unset stage to remove unneeded fields.添加未设置的阶段以删除不需要的字段。

Finally, add an $unset stage. The $unset stage removes the _id and description fields from the result documents:最后,添加一个$unset阶段。$unset阶段从结果文档中删除_id和描述字段:

"{", "$unset", "[", BCON_UTF8("_id"), BCON_UTF8("description"), "]", "}",
4

Run the aggregation pipeline.运行聚合管道。

Add the following code to the end of your application to perform the aggregation on the products collection:将以下代码添加到应用程序的末尾,以对products集合执行聚合:

mongoc_cursor_t *results =
mongoc_collection_aggregate(products, MONGOC_QUERY_NONE, pipeline, NULL, NULL);

bson_destroy(&embedded_pipeline);
bson_destroy(pipeline);

Ensure that you clean up the collection resources by adding the following line to your cleanup statements:通过在清理语句中添加以下行来确保清理集合资源:

mongoc_collection_destroy(products);
mongoc_collection_destroy(orders);

Finally, run the following commands in your shell to generate and run the executable:最后,在shell中运行以下命令以生成并运行可执行文件:

gcc -o aggc agg-tutorial.c $(pkg-config --libs --cflags libmongoc-1.0)
./aggc

Tip

If you encounter connection errors by running the preceding commands in one call, you can run them separately.如果在一次调用中运行上述命令时遇到连接错误,可以单独运行它们。

5

Interpret the aggregation results.解释聚合结果。

The aggregated result contains two documents. The documents represent products for which there were orders placed in 2020. Each document contains an orders array field that lists details about each order for that product:聚合结果包含两个文档。这些文件代表了2020年下订单的产品。每个文档都包含一个orders数组字段,其中列出了该产品的每个订单的详细信息:

{ "name" : "Asus Laptop", "variation" : "Standard Display", "category" : "ELECTRONICS", "orders" : [ { "customer_id" : "elise_smith@myemail.com", "orderdate" : { "$date" : { "$numberLong" : "1590822952000" } }, "value" : { "$numberDouble" : "431.43000000000000682" } }, { "customer_id" : "jjones@tepidmail.com", "orderdate" : { "$date" : { "$numberLong" : "1608976546000" } }, "value" : { "$numberDouble" : "429.64999999999997726" } } ] }
{ "name" : "Morphy Richards Food Mixer", "variation" : "Deluxe", "category" : "KITCHENWARE", "orders" : [ { "customer_id" : "oranieri@warmmail.com", "orderdate" : { "$date" : { "$numberLong" : "1577869537000" } }, "value" : { "$numberDouble" : "63.130000000000002558" } } ] }

The result documents contain details from documents in the orders collection and the products collection, joined by the product names and variations.结果文档包含orders集合和products集合中文档的详细信息,以及产品名称和变体。

C++11
1

Add a lookup stage to link the collections and import fields.添加查找阶段以链接集合和导入字段。

The first stage of the pipeline is a $lookup stage to join the orders collection to the products collection by two fields in each collection. The lookup stage contains an embedded pipeline to configure the join.管道的第一阶段是$lookup阶段,通过每个集合中的两个字段将orders集合连接到products集合。查找阶段包含一个用于配置连接的嵌入式管道。

Within the embedded pipeline, add a $match stage to match the values of two fields on each side of the join. 在嵌入式管道中,添加一个$match阶段,以匹配连接两侧两个字段的值。Note that the following code uses aliases for the name and variation fields set when creating the $lookup stage:请注意,以下代码在创建$lookup阶段时为namevariation字段设置了别名:

auto embed_match_stage1 = bsoncxx::from_json(R"({
"$match": {
"$expr": {
"$and": [
{ "$eq": ["$product_name", "$$prdname"] },
{ "$eq": ["$product_variation", "$$prdvartn"] }
]
}
}
})");

Within the embedded pipeline, add another $match stage to match orders placed in 2020:在嵌入式管道中,添加另一个$match阶段来匹配2020年的订单:

auto embed_match_stage2 = bsoncxx::from_json(R"({
"$match": {
"orderdate": {
"$gte": { "$date": 1577836800000 },
"$lt": { "$date": 1609459200000 }
}
}
})");

Within the embedded pipeline, add an $unset stage to remove unneeded fields from the orders collection side of the join:在嵌入式管道中,添加一个$unset阶段,从连接的orders集合端删除不需要的字段:

auto embed_unset_stage = bsoncxx::from_json(R"({
"$unset": ["_id", "product_name", "product_variation"]
})");

After the embedded pipeline is completed, add the $lookup stage to the main aggregation pipeline. Configure this stage to store the processed lookup fields in an array field called orders:嵌入式管道完成后,将$lookup阶段添加到主聚合管道中。配置此阶段以将处理后的查找字段存储在名为orders的数组字段中:

pipeline.lookup(make_document(
kvp("from", "orders"),
kvp("let", make_document(
kvp("prdname", "$name"),
kvp("prdvartn", "$variation")
)),
kvp("pipeline", make_array(embed_match_stage1, embed_match_stage2, embed_unset_stage)),
kvp("as", "orders")
));
2

Add a match stage for products ordered in 2020.为2020年订购的产品添加匹配阶段。

Next, add a $match stage to only show products for which there is at least one order in 2020, based on the orders array calculated in the previous step:接下来,根据上一步计算的orders数组,添加一个$match阶段,仅显示2020年至少有一个订单的产品:

pipeline.match(bsoncxx::from_json(R"({
"orders": { "$ne": [] }
})"));
3

Add an unset stage to remove unneeded fields.添加未设置的阶段以删除不需要的字段。

Finally, add an $unset stage. The $unset stage removes the _id and description fields from the result documents:最后,添加一个$unset阶段。$unset阶段从结果文档中删除_iddescription字段:

pipeline.append_stage(bsoncxx::from_json(R"({
"$unset": ["_id", "description"]
})"));
4

Run the aggregation pipeline.运行聚合管道。

Add the following code to the end of your application to perform the aggregation on the products collection:将以下代码添加到应用程序的末尾,以对products集合执行聚合:

auto cursor = products.aggregate(pipeline);

Finally, run the following command in your shell to start your application:最后,在shell中运行以下命令以启动应用程序:

c++ --std=c++17 agg-tutorial.cpp $(pkg-config --cflags --libs libmongocxx) -o ./app.out
./app.out
5

Interpret the aggregation results.解释聚合结果。

The aggregated result contains two documents. The documents represent products for which there were orders placed in 2020. Each document contains an orders array field that lists details about each order for that product:聚合结果包含两个文档。这些文件代表了2020年下订单的产品。每个文档都包含一个orders数组字段,其中列出了该产品的每个订单的详细信息:

{ "name" : "Asus Laptop", "variation" : "Standard Display", "category" : "ELECTRONICS",
"orders" : [ { "customer_id" : "elise_smith@myemail.com", "orderdate" : { "$date" : "2020-05-30T06:55:52Z" },
"value" : 431.43000000000000682 }, { "customer_id" : "jjones@tepidmail.com", "orderdate" : { "$date" :
"2020-12-26T08:55:46Z" }, "value" : 429.64999999999997726 } ] }
{ "name" : "Morphy Richards Food Mixer", "variation" : "Deluxe", "category" : "KITCHENWARE",
"orders" : [ { "customer_id" : "oranieri@warmmail.com", "orderdate" : { "$date" : "2020-01-01T06:45:37Z" },
"value" : 63.130000000000002558 } ] }

The result documents contain details from documents in the orders collection and the products collection, joined by the product names and variations.结果文档包含orders集合和products集合中文档的详细信息,以及产品名称和变体。

C#
1

Add a lookup stage to link the collections and import fields.添加查找阶段以链接集合和导入字段。

The first stage of the pipeline is a $lookup stage to join the orders collection to the products collection by two fields in each collection. The lookup stage contains an embedded pipeline to configure the join.管道的第一阶段是$lookup阶段,通过每个集合中的两个字段将orders集合连接到products集合。查找阶段包含一个用于配置连接的嵌入式管道。

Instantiate the embedded pipeline, then chain a $match stage to match the values of two fields on each side of the join. Note that the following code uses aliases for the Name and Variation fields set when creating the $lookup stage:实例化嵌入式管道,然后链接一个$match阶段,以匹配连接两侧两个字段的值。请注意,以下代码在创建$lookup阶段时为NameVariation字段设置了别名:

var embeddedPipeline = new EmptyPipelineDefinition<Order>()
.Match(new BsonDocument("$expr",
new BsonDocument("$and", new BsonArray
{
new BsonDocument("$eq", new BsonArray { "$ProductName", "$$prdname" }),
new BsonDocument("$eq", new BsonArray { "$ProductVariation", "$$prdvartn" })
})))

Within the embedded pipeline, add another $match stage to match orders placed in 2020:在嵌入式管道中,添加另一个$match阶段来匹配2020年的订单:

.Match(o => o.OrderDate >= DateTime.Parse("2020-01-01T00:00:00Z") &&
o.OrderDate < DateTime.Parse("2021-01-01T00:00:00Z"))

Within the embedded pipeline, add a $project stage to remove unneeded fields from the orders collection side of the join:在嵌入式管道中,添加一个$project阶段,从连接的orders集合端删除不需要的字段:

.Project(Builders<Order>.Projection
.Exclude(o => o.Id)
.Exclude(o => o.ProductName)
.Exclude(o => o.ProductVariation));

After the embedded pipeline is completed, start the main aggregation on the products collection and chain the $lookup stage. Configure this stage to store the processed lookup fields in an array field called Orders:嵌入式管道完成后,启动products集合上的主聚合,并链接$lookup阶段。配置此阶段以将处理后的查找字段存储在名为Orders的数组字段中:

var results = products.Aggregate()
.Lookup<Order, BsonDocument, IEnumerable<BsonDocument>, BsonDocument>(
foreignCollection: orders,
let: new BsonDocument { { "prdname", "$Name" }, { "prdvartn", "$Variation" } },
lookupPipeline: embeddedPipeline,
"Orders"
)
2

Add a match stage for products ordered in 2020.为2020年订购的产品添加匹配阶段。

Next, add a $match stage to only show products for which there is at least one order in 2020, based on the Orders array created in the previous step:接下来,根据上一步创建的Orders数组,添加一个$match阶段,仅显示2020年至少有一个订单的产品:

.Match(Builders<BsonDocument>.Filter.Ne("Orders", new BsonArray()))
3

Add a projection stage to remove unneeded fields.添加投影台以删除不需要的字段。

Finally, add a $project stage. The $project stage removes the _id and Description fields from the result documents:最后,添加一个$project阶段。$project阶段从结果文档中删除_id和Description字段:

.Project(Builders<BsonDocument>.Projection
.Exclude("_id")
.Exclude("Description")
);
4

Run the aggregation and interpret the results.运行聚合并解释结果。

Finally, run the application in your IDE and inspect the results.最后,在IDE中运行应用程序并检查结果。

The aggregated result contains two documents. The documents represent products for which there were orders placed in 2020. Each document contains an Orders array field that lists details about each order for that product:聚合结果包含两个文档。这些文件代表了2020年下订单的产品。每个文档都包含一个Orders数组字段,其中列出了该产品的每个订单的详细信息:

{ "Name" : "Asus Laptop", "Variation" : "Standard Display", "Category" : "ELECTRONICS", "Orders" : [{ "CustomerId" : "elise_smith@myemail.com", "OrderDate" : { "$date" : "2020-05-30T08:35:52Z" }, "Value" : 431.43000000000001 }, { "CustomerId" : "jjones@tepidmail.com", "OrderDate" : { "$date" : "2020-12-26T08:55:46Z" }, "Value" : 429.64999999999998 }] }
{ "Name" : "Morphy Richards Food Mixer", "Variation" : "Deluxe", "Category" : "KITCHENWARE", "Orders" : [{ "CustomerId" : "oranieri@warmmail.com", "OrderDate" : { "$date" : "2020-01-01T08:25:37Z" }, "Value" : 63.130000000000003 }] }

The result documents contain details from documents in the orders collection and the products collection, joined by the product names and variations.结果文档包含orders集合和products集合中文档的详细信息,以及产品名称和变体。

Go
1

Add a lookup stage to link the collections and import fields.添加查找阶段以链接集合和导入字段。

The first stage of the pipeline is a $lookup stage to join the orders collection to the products collection by two fields in each collection. The lookup stage contains an embedded pipeline to configure the join.管道的第一阶段是$lookup阶段,通过每个集合中的两个字段将orders集合连接到产品集合。查找阶段包含一个用于配置连接的嵌入式管道。

Within the embedded pipeline, add a $match stage to match the values of two fields on each side of the join. 在嵌入式管道中,添加一个$match阶段,以匹配连接两侧两个字段的值。Note that the following code uses aliases for the name and variation fields set when creating the $lookup stage:请注意,以下代码在创建$lookup阶段时为namevariation字段设置了别名:

embeddedMatchProductInfoStage := bson.D{
{Key: "$match", Value: bson.D{
{Key: "$expr", Value: bson.D{
{Key: "$and", Value: bson.A{
bson.D{{Key: "$eq", Value: bson.A{"$product_name", "$$prdname"}}},
bson.D{{Key: "$eq", Value: bson.A{"$product_variation", "$$prdvartn"}}},
}},
}},
}},
}

Within the embedded pipeline, add another $match stage to match orders placed in 2020:在嵌入式管道中,添加另一个$match阶段来匹配2020年的订单:

embeddedMatchOrderDateStage := bson.D{
{Key: "$match", Value: bson.D{
{Key: "orderdate", Value: bson.D{
{Key: "$gte", Value: time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC)},
{Key: "$lt", Value: time.Date(2021, 1, 1, 0, 0, 0, 0, time.UTC)},
}},
}},
}

Within the embedded pipeline, add an $unset stage to remove unneeded fields from the orders collection side of the join:在嵌入式管道中,添加一个$unset阶段,从连接的orders集合端删除不需要的字段:

embeddedUnsetStage := bson.D{
{Key: "$unset", Value: bson.A{"_id", "product_name", "product_variation"}},
}

After the embedded pipeline is completed, add the $lookup stage to the main aggregation pipeline. Configure this stage to store the processed lookup fields in an array field called orders:嵌入式管道完成后,将$lookup阶段添加到主聚合管道中。配置此阶段以将处理后的查找字段存储在名为orders的数组字段中:

embeddedPipeline := mongo.Pipeline{embeddedMatchProductInfoStage, embeddedMatchOrderDateStage, embeddedUnsetStage}

lookupStage := bson.D{
{Key: "$lookup", Value: bson.D{
{Key: "from", Value: "orders"},
{Key: "let", Value: bson.D{
{Key: "prdname", Value: "$name"},
{Key: "prdvartn", Value: "$variation"},
}},
{Key: "pipeline", Value: embeddedPipeline},
{Key: "as", Value: "orders"},
}},
}
2

Add a match stage for products ordered in 2020.为2020年订购的产品添加匹配阶段。

Next, add a $match stage to only show products for which there is at least one order in 2020, based on the orders array calculated in the previous step:接下来,根据上一步计算的orders数组,添加一个$match阶段,仅显示2020年至少有一个订单的产品:

matchStage := bson.D{
{Key: "$match", Value: bson.D{
{Key: "orders", Value: bson.D{{Key: "$ne", Value: bson.A{}}}},
}},
}
3

Add an unset stage to remove unneeded fields.添加未设置的阶段以删除不需要的字段。

Finally, add an $unset stage. The $unset stage removes the _id and description fields from the result documents:最后,添加一个$unset阶段。$unset阶段从结果文档中删除_iddescription字段:

unsetStage := bson.D{
{Key: "$unset", Value: bson.A{"_id", "description"}},
}
4

Run the aggregation pipeline.运行聚合管道。

Add the following code to the end of your application to perform the aggregation on the products collection:将以下代码添加到应用程序的末尾,以对products集合执行聚合:

pipeline := mongo.Pipeline{lookupStage, matchStage, unsetStage}
cursor, err := products.Aggregate(ctx, pipeline)

Finally, run the application and inspect the results.最后,运行应用程序并检查结果。

5

Interpret the aggregation results.解释聚合结果。

The aggregated result contains two documents. The documents represent products for which there were orders placed in 2020. Each document contains an orders array field that lists details about each order for that product:聚合结果包含两个文档。这些文件代表了2020年下订单的产品。每个文档都包含一个orders数组字段,其中列出了该产品的每个订单的详细信息:

{"name":"Asus Laptop","variation":"Standard Display","category":"ELECTRONICS","orders":[{"customer_id":"elise_smith@myemail.com","orderdate":{"$date":"2020-05-30T08:35:52Z"},"value":431.42999267578125},{"customer_id":"jjones@tepidmail.com","orderdate":{"$date":"2020-12-26T08:55:46Z"},"value":429.6499938964844}]}
{"name":"Morphy Richards Food Mixer","variation":"Deluxe","category":"KITCHENWARE","orders":[{"customer_id":"oranieri@warmmail.com","orderdate":{"$date":"2020-01-01T08:25:37Z"},"value":63.130001068115234}]}

The result documents contain details from documents in the orders collection and the products collection, joined by the product names and variations.结果文档包含orders集合和products集合中文档的详细信息,以及产品名称和变体。

Java(Sync)
1

Add a lookup stage to link the collections and import fields.添加查找阶段以链接集合和导入字段。

The first stage of the pipeline is a $lookup stage to join the orders collection to the products collection by two fields in each collection. The lookup stage contains an embedded pipeline to configure the join.管道的第一阶段是$lookup阶段,通过每个集合中的两个字段将orders集合连接到products集合。查找阶段包含一个用于配置连接的嵌入式管道。

Within the embedded pipeline, add a $match stage to match the values of two fields on each side of the join. Note that the following code uses aliases for the name and variation fields set when creating the $lookup stage:在嵌入式管道中,添加一个$match阶段,以匹配连接两侧两个字段的值。请注意,以下代码在创建$lookup阶段时为namevariation字段设置了别名:

List<Bson> embeddedPipeline = new ArrayList<>();

embeddedPipeline.add(Aggregates.match(
Filters.expr(
Filters.and(
new Document("$eq", Arrays.asList("$product_name", "$$prdname")),
new Document("$eq", Arrays.asList("$product_variation", "$$prdvartn"))
)
)
));

Within the embedded pipeline, add another $match stage to match orders placed in 2020:在嵌入式管道中,添加另一个$match阶段来匹配2020年的订单:

embeddedPipeline.add(Aggregates.match(Filters.and(
Filters.gte("orderdate", LocalDateTime.parse("2020-01-01T00:00:00")),
Filters.lt("orderdate", LocalDateTime.parse("2021-01-01T00:00:00"))
)));

Within the embedded pipeline, add an $unset stage to remove unneeded fields from the orders collection side of the join:在嵌入式管道中,添加一个$unset阶段,从连接的orders集合端删除不需要的字段:

embeddedPipeline.add(Aggregates.unset("_id", "product_name", "product_variation"));

After the embedded pipeline is completed, add the $lookup stage to the main aggregation pipeline. Configure this stage to store the processed lookup fields in an array field called orders:嵌入式管道完成后,将$lookup阶段添加到主聚合管道中。配置此阶段以将处理后的查找字段存储在名为orders的数组字段中:

pipeline.add(Aggregates.lookup(
"orders",
Arrays.asList(
new Variable<>("prdname", "$name"),
new Variable<>("prdvartn", "$variation")
),
embeddedPipeline,
"orders"
));
2

Add a match stage for products ordered in 2020.为2020年订购的产品添加匹配阶段。

Next, add a $match stage to only show products for which there is at least one order in 2020, based on the orders array calculated in the previous step:接下来,根据上一步计算的orders数组,添加一个$match阶段,仅显示2020年至少有一个订单的产品:

pipeline.add(Aggregates.match(
Filters.ne("orders", new ArrayList<>())
));
3

Add an unset stage to remove unneeded fields.添加未设置的阶段以删除不需要的字段。

Finally, add an $unset stage. The $unset stage removes the _id and description fields from the result documents:最后,添加一个$unset阶段。$unset阶段从结果文档中删除_iddescription字段:

pipeline.add(Aggregates.unset("_id", "description"));
4

Run the aggregation pipeline.运行聚合管道。

Add the following code to the end of your application to perform the aggregation on the products collection:将以下代码添加到应用程序的末尾,以对products集合执行聚合:

AggregateIterable<Document> aggregationResult = products.aggregate(pipeline);

Finally, run the application in your IDE.最后,在IDE中运行应用程序。

5

Interpret the aggregation results.解释聚合结果。

The aggregated result contains two documents. The documents represent products for which there were orders placed in 2020. Each document contains an orders array field that lists details about each order for that product:聚合结果包含两个文档。这些文件代表了2020年下订单的产品。每个文档都包含一个orders数组字段,其中列出了该产品的每个订单的详细信息:

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

The result documents contain details from documents in the orders collection and the products collection, joined by the product names and variations.结果文档包含orders集合和products集合中文档的详细信息,以及产品名称和变体。

Kotlin(Coroutine)
1

Add a lookup stage to link the collections and import fields.添加查找阶段以链接集合和导入字段。

The first stage of the pipeline is a $lookup stage to join the orders collection to the products collection by two fields in each collection. The lookup stage contains an embedded pipeline to configure the join.管道的第一阶段是$lookup阶段,通过每个集合中的两个字段将orders集合连接到products集合。查找阶段包含一个用于配置连接的嵌入式管道。

Within the embedded pipeline, add a $match stage to match the values of two fields on each side of the join. Note that the following code uses aliases for the name and variation fields set when creating the $lookup stage:在嵌入式管道中,添加一个$match阶段,以匹配连接两侧两个字段的值。请注意,以下代码在创建$lookup阶段时为namevariation字段设置了别名:

val embeddedPipeline = mutableListOf<Bson>()

embeddedPipeline.add(
Aggregates.match(
Filters.expr(
Document(
"\$and", listOf(
Document("\$eq", listOf("\$${Order::productName.name}", "$\$prdname")),
Document("\$eq", listOf("\$${Order::productVariation.name}", "$\$prdvartn"))
)
)
)
)
)

Within the embedded pipeline, add another $match stage to match orders placed in 2020:在嵌入式管道中,添加另一个$match阶段来匹配2020年的订单:

embeddedPipeline.add(
Aggregates.match(
Filters.and(
Filters.gte(
Order::orderDate.name,
LocalDateTime.parse("2020-01-01T00:00:00").toJavaLocalDateTime()
),
Filters.lt(Order::orderDate.name, LocalDateTime.parse("2021-01-01T00:00:00").toJavaLocalDateTime())
)
)
)

Within the embedded pipeline, add an $unset stage to remove unneeded fields from the orders collection side of the join:在嵌入式管道中,添加一个$unset阶段,从连接的orders集合端删除不需要的字段:

embeddedPipeline.add(Aggregates.unset("_id", Order::productName.name, Order::productVariation.name))

After the embedded pipeline is completed, add the $lookup stage to the main aggregation pipeline. Configure this stage to store the processed lookup fields in an array field called orders:嵌入式管道完成后,将$lookup阶段添加到主聚合管道中。配置此阶段以将处理后的查找字段存储在名为orders的数组字段中:

pipeline.add(
Aggregates.lookup(
"orders",
listOf(
Variable("prdname", "\$${Product::name.name}"),
Variable("prdvartn", "\$${Product::variation.name}")
),
embeddedPipeline,
"orders"
)
)
2

Add a match stage for products ordered in 2020.为2020年订购的产品添加匹配阶段。

Next, add a $match stage to only show products for which there is at least one order in 2020, based on the orders array calculated in the previous step:接下来,根据上一步计算的orders数组,添加一个$match阶段,仅显示2020年至少有一个订单的产品:

pipeline.add(
Aggregates.match(
Filters.ne("orders", mutableListOf<Document>())
)
)
3

Add an unset stage to remove unneeded fields.添加未设置的阶段以删除不需要的字段。

Finally, add an $unset stage. The $unset stage removes the _id and description fields from the result documents:最后,添加一个$unset阶段。$unset阶段从结果文档中删除_id和描述字段:

pipeline.add(Aggregates.unset("_id", "description"))
4

Run the aggregation pipeline.运行聚合管道。

Add the following code to the end of your application to perform the aggregation on the products collection:将以下代码添加到应用程序的末尾,以对products集合执行聚合:

val aggregationResult = products.aggregate<Document>(pipeline)

Finally, run the application in your IDE.最后,在IDE中运行应用程序。

5

Interpret the aggregation results.解释聚合结果。

The aggregated result contains two documents. The documents represent products for which there were orders placed in 2020. Each document contains an orders array field that lists details about each order for that product:聚合结果包含两个文档。这些文件代表了2020年下订单的产品。每个文档都包含一个orders数组字段,其中列出了该产品的每个订单的详细信息:

Document{{name=Asus Laptop, variation=Standard Display, category=ELECTRONICS, orders=[Document{{customerID=elise_smith@myemail.com, orderDate=Sat May 30 04:35:52 EDT 2020, value=431.43}}, Document{{customerID=jjones@tepidmail.com, orderDate=Sat Dec 26 03:55:46 EST 2020, value=429.65}}]}}
Document{{name=Morphy Richards Food Mixer, variation=Deluxe, category=KITCHENWARE, orders=[Document{{customerID=oranieri@warmmail.com, orderDate=Wed Jan 01 03:25:37 EST 2020, value=63.13}}]}}

The result documents contain details from documents in the orders collection and the products collection, joined by the product names and variations.结果文档包含orders集合和products集合中文档的详细信息,以及产品名称和变体。

Node.js
1

Add a lookup stage to link the collections and import fields.添加查找阶段以链接集合和导入字段。

The first stage of the pipeline is a $lookup stage to join the orders collection to the products collection by two fields in each collection. The lookup stage contains an embedded pipeline to configure the join.管道的第一阶段是$lookup阶段,通过每个集合中的两个字段将orders集合连接到products集合。查找阶段包含一个用于配置连接的嵌入式管道。

Within the embedded pipeline, add a $match stage to match the values of two fields on each side of the join. 在嵌入式管道中,添加一个$match阶段,以匹配连接两侧两个字段的值。Note that the following code uses aliases for the name and variation fields set when creating the $lookup stage:请注意,以下代码在创建$lookup阶段时为namevariation字段设置了别名:

const embedded_pl = [];

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

Within the embedded pipeline, add another $match stage to match orders placed in 2020:在嵌入式管道中,添加另一个$match阶段来匹配2020年的订单:

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

Within the embedded pipeline, add an $unset stage to remove unneeded fields from the orders collection side of the join:在嵌入式管道中,添加一个$unset阶段,从连接的orders集合端删除不需要的字段:

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

After the embedded pipeline is completed, add the $lookup stage to the main aggregation pipeline. Configure this stage to store the processed lookup fields in an array field called orders:嵌入式管道完成后,将$lookup阶段添加到主聚合管道中。配置此阶段以将处理后的查找字段存储在名为orders的数组字段中:

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

Add a match stage for products ordered in 2020.为2020年订购的产品添加匹配阶段。

Next, add a $match stage to only show products for which there is at least one order in 2020, based on the orders array calculated in the previous step:接下来,根据上一步计算的orders数组,添加一个$match阶段,仅显示2020年至少有一个订单的产品:

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

Add an unset stage to remove unneeded fields.添加未设置的阶段以删除不需要的字段。

Finally, add an $unset stage. The $unset stage removes the _id and description fields from the result documents:最后,添加一个$unset阶段。$unset阶段从结果文档中删除_iddescription字段:

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

Run the aggregation pipeline.运行聚合管道。

Add the following code to the end of your application to perform the aggregation on the products collection:将以下代码添加到应用程序的末尾,以对products集合执行聚合:

const aggregationResult = await products.aggregate(pipeline);

Finally, execute the code in the file using your IDE or the command line.最后,使用IDE或命令行执行文件中的代码。

5

Interpret the aggregation results.解释聚合结果。

The aggregated result contains two documents. The documents represent products for which there were orders placed in 2020. Each document contains an orders array field that lists details about each order for that product:聚合结果包含两个文档。这些文件代表了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
}
]
}

The result documents contain details from documents in the orders collection and the products collection, joined by the product names and variations.结果文档包含orders集合和products集合中文档的详细信息,以及产品名称和变体。

PHP
1

Add a lookup stage to link the collections and import fields.添加查找阶段以链接集合和导入字段。

The first stage of the pipeline is a $lookup stage to join the orders collection to the products collection by two fields in each collection. The lookup stage contains an embedded pipeline to configure the join. First, create the embedded pipeline:管道的第一阶段是$lookup阶段,通过每个集合中的两个字段将orders集合连接到products集合。查找阶段包含一个用于配置连接的嵌入式管道。首先,创建嵌入式管道:

$embeddedPipeline = new Pipeline(
// Add stages within embedded pipeline.
};

Within the embedded pipeline, add a $match stage to match the values of two fields on each side of the join. Note that the following code uses aliases for the name and variation fields set when creating the $lookup stage:在嵌入式管道中,添加一个$match阶段,以匹配连接两侧两个字段的值。请注意,以下代码在创建$lookup阶段时为namevariation字段设置了别名:

Stage::match(
Query::expr(
Expression::and(
Expression::eq(
Expression::stringFieldPath('product_name'),
Expression::variable('prdname')
),
Expression::eq(
Expression::stringFieldPath('product_variation'),
Expression::variable('prdvartn')
),
)
)
),

Within the embedded pipeline, add another $match stage to match orders placed in 2020:在嵌入式管道中,添加另一个$match阶段来匹配2020年的订单:

Stage::match(
orderdate: [
Query::gte(new UTCDateTime(new DateTimeImmutable('2020-01-01T00:00:00'))),
Query::lt(new UTCDateTime(new DateTimeImmutable('2021-01-01T00:00:00'))),
]
),

Within the embedded pipeline, add an $unset stage to remove unneeded fields from the orders collection side of the join:在嵌入式管道中,添加一个$unset阶段,从连接的orders集合端删除不需要的字段:

Stage::unset('_id', 'product_name', 'product_variation')

Next, outside of your Pipeline instances, create the $lookup stage in a factory function. Configure this stage to store the processed lookup fields in an array field called orders:接下来,在Pipeline实例之外,在工厂函数中创建$lookup阶段。配置此阶段以将处理后的查找字段存储在名为orders的数组字段中:

function lookupOrdersStage(Pipeline $embeddedPipeline)
{
return Stage::lookup(
from: 'orders',
let: object(
prdname: Expression::stringFieldPath('name'),
prdvartn: Expression::stringFieldPath('variation'),
),
pipeline: $embeddedPipeline,
as: 'orders',
);
}

Then, in your main Pipeline instance, call the lookupOrdersStage() function:然后,在主Pipeline实例中,调用lookupOrdersStage()函数:

lookupOrdersStage($embeddedPipeline),
2

Add a match stage for products ordered in 2020.为2020年订购的产品添加匹配阶段。

Next, add a $match stage to only show products for which there is at least one order in 2020, based on the orders array calculated in the previous step:接下来,根据上一步计算的orders数组,添加一个$match阶段,仅显示2020年至少有一个订单的产品:

Stage::match(
orders: Query::ne([])
),
3

Add an unset stage to remove unneeded fields.添加未设置的阶段以删除不需要的字段。

Finally, add an $unset stage. The $unset stage removes the _id and description fields from the result documents:最后,添加一个$unset阶段。$unset阶段从结果文档中删除_iddescription字段:

Stage::unset('_id', 'description')
4

Run the aggregation pipeline.运行聚合管道。

Add the following code to the end of your application to perform the aggregation on the products collection:将以下代码添加到应用程序的末尾,以对products集合执行聚合:

$cursor = $products->aggregate($pipeline);

Finally, run the following command in your shell to start your application:最后,在shell中运行以下命令以启动应用程序:

php agg_tutorial.php
5

Interpret the aggregation results.解释聚合结果。

The aggregated result contains two documents. The documents represent products for which there were orders placed in 2020. Each document contains an orders array field that lists details about each order for that product:聚合结果包含两个文档。这些文件代表了2020年下订单的产品。每个文档都包含一个orders数组字段,其中列出了该产品的每个订单的详细信息:

{
"name": "Asus Laptop",
"variation": "Standard Display",
"category": "ELECTRONICS",
"orders": [
{
"customer_id": "elise_smith@myemail.com",
"orderdate": {
"$date": {
"$numberLong": "1590827752000"
}
},
"value": 431.43
},
{
"customer_id": "jjones@tepidmail.com",
"orderdate": {
"$date": {
"$numberLong": "1608972946000"
}
},
"value": 429.65
}
]
}
{
"name": "Morphy Richards Food Mixer",
"variation": "Deluxe",
"category": "KITCHENWARE",
"orders": [
{
"customer_id": "oranieri@warmmail.com",
"orderdate": {
"$date": {
"$numberLong": "1577867137000"
}
},
"value": 63.13
}
]
}

The result documents contain details from documents in the orders collection and the products collection, joined by the product names and variations.结果文档包含orders集合和products集合中文档的详细信息,以及产品名称和变体。

Python
1

Add a lookup stage to link the collections and import fields.添加查找阶段以链接集合和导入字段。

The first stage of the pipeline is a $lookup stage to join the orders collection to the products collection by two fields in each collection. The lookup stage contains an embedded pipeline to configure the join.管道的第一阶段是$lookup阶段,通过每个集合中的两个字段将orders集合连接到products集合。查找阶段包含一个用于配置连接的嵌入式管道。

Within the embedded pipeline, add a $match stage to match the values of two fields on each side of the join. 在嵌入式管道中,添加一个$match阶段,以匹配连接两侧两个字段的值。Note that the following code uses aliases for the name and variation fields set when creating the $lookup stage:请注意,以下代码在创建$lookup阶段时为namevariation字段设置了别名:

embedded_pl = [
{
"$match": {
"$expr": {
"$and": [
{"$eq": ["$product_name", "$$prdname"]},
{"$eq": ["$product_variation", "$$prdvartn"]},
]
}
}
}
]

Within the embedded pipeline, add another $match stage to match orders placed in 2020:在嵌入式管道中,添加另一个$match阶段来匹配2020年的订单:

embedded_pl.append(
{
"$match": {
"orderdate": {
"$gte": datetime(2020, 1, 1, 0, 0, 0),
"$lt": datetime(2021, 1, 1, 0, 0, 0),
}
}
}
)

Within the embedded pipeline, add an $unset stage to remove unneeded fields from the orders collection side of the join:在嵌入式管道中,添加一个$unset阶段,从连接的orders集合端删除不需要的字段:

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

After the embedded pipeline is completed, add the $lookup stage to the main aggregation pipeline. Configure this stage to store the processed lookup fields in an array field called orders:嵌入式管道完成后,将$lookup阶段添加到主聚合管道中。配置此阶段以将处理后的查找字段存储在名为orders的数组字段中:

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

Add a match stage for products ordered in 2020.为2020年订购的产品添加匹配阶段。

Next, add a $match stage to only show products for which there is at least one order in 2020, based on the orders array calculated in the previous step:接下来,根据上一步计算的orders数组,添加一个$match阶段,仅显示2020年至少有一个订单的产品:

pipeline.append({"$match": {"orders": {"$ne": []}}})
3

Add an unset stage to remove unneeded fields.添加未设置的阶段以删除不需要的字段。

Finally, add an $unset stage. The $unset stage removes the _id and description fields from the result documents:最后,添加一个$unset阶段。$unset阶段从结果文档中删除_iddescription字段:

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

Run the aggregation pipeline.运行聚合管道。

Add the following code to the end of your application to perform the aggregation on the products collection:将以下代码添加到应用程序的末尾,以对products集合执行聚合:

aggregation_result = products_coll.aggregate(pipeline)

Finally, run the following command in your shell to start your application:最后,在shell中运行以下命令以启动应用程序:

python3 agg_tutorial.py
5

Interpret the aggregation results.解释聚合结果。

The aggregated result contains two documents. The documents represent products for which there were orders placed in 2020. Each document contains an orders array field that lists details about each order for that product:聚合结果包含两个文档。这些文件代表了2020年下订单的产品。每个文档都包含一个orders数组字段,其中列出了该产品的每个订单的详细信息:

{'name': 'Asus Laptop', 'variation': 'Standard Display', 'category': 'ELECTRONICS', 'orders': [{'customer_id': 'elise_smith@myemail.com', 'orderdate': datetime.datetime(2020, 5, 30, 8, 35, 52), 'value': 431.43}, {'customer_id': 'jjones@tepidmail.com', 'orderdate': datetime.datetime(2020, 12, 26, 8, 55, 46), 'value': 429.65}]}
{'name': 'Morphy Richards Food Mixer', 'variation': 'Deluxe', 'category': 'KITCHENWARE', 'orders': [{'customer_id': 'oranieri@warmmail.com', 'orderdate': datetime.datetime(2020, 1, 1, 8, 25, 37), 'value': 63.13}]}

The result documents contain details from documents in the orders collection and the products collection, joined by the product names and variations.结果文档包含orders集合和products集合中文档的详细信息,以及产品名称和变体。

Ruby
1

Add a lookup stage to link the collections and import fields.添加查找阶段以链接集合和导入字段。

The first stage of the pipeline is a $lookup stage to join the orders collection to the products collection by two fields in each collection. The lookup stage contains an embedded pipeline to configure the join.管道的第一阶段是$lookup阶段,通过每个集合中的两个字段将orders集合连接到products集合。查找阶段包含一个用于配置连接的嵌入式管道。

Within the embedded pipeline, add a $match stage to match the values of two fields on each side of the join. 在嵌入式管道中,添加一个$match阶段,以匹配连接两侧两个字段的值。Note that the following code uses aliases for the name and variation fields set when creating the $lookup stage:请注意,以下代码在创建$lookup阶段时为namevariation字段设置了别名:

{
"$match": {
"$expr": {
"$and": [
{ "$eq": ["$product_name", "$$prdname"] },
{ "$eq": ["$product_variation", "$$prdvartn"] },
],
},
},
},

Within the embedded pipeline, add another $match stage to match orders placed in 2020:在嵌入式管道中,添加另一个$match阶段来匹配2020年的订单:

{
"$match": {
orderdate: {
"$gte": DateTime.parse("2020-01-01T00:00:00Z"),
"$lt": DateTime.parse("2021-01-01T00:00:00Z"),
},
},
},

Within the embedded pipeline, add an $unset stage to remove unneeded fields from the orders collection side of the join:在嵌入式管道中,添加一个$unset阶段,从连接的orders集合端删除不需要的字段:

{
"$unset": ["_id", "product_name", "product_variation"],
},

After the embedded pipeline is completed, add the $lookup stage to the main aggregation pipeline. Configure this stage to store the processed lookup fields in an array field called orders:嵌入式管道完成后,将$lookup阶段添加到主聚合管道中。配置此阶段以将处理后的查找字段存储在名为orders的数组字段中:

{
"$lookup": {
from: "orders",
let: {
prdname: "$name",
prdvartn: "$variation",
},
pipeline: embedded_pipeline,
as: "orders",
},
},
2

Add a match stage for products ordered in 2020.为2020年订购的产品添加匹配阶段。

Next, add a $match stage to only show products for which there is at least one order in 2020, based on the orders array calculated in the previous step:接下来,根据上一步计算的orders数组,添加一个$match阶段,仅显示2020年至少有一个订单的产品:

{
"$match": {
orders: { "$ne": [] },
},
},
3

Add an unset stage to remove unneeded fields.添加未设置的阶段以删除不需要的字段。

Finally, add an $unset stage. The $unset stage removes the _id and description fields from the result documents:最后,添加一个$unset阶段。$unset阶段从结果文档中删除_id和描述字段:

{
"$unset": ["_id", "description"],
},
4

Run the aggregation pipeline.运行聚合管道。

Add the following code to the end of your application to perform the aggregation on the products collection:将以下代码添加到应用程序的末尾,以对products集合执行聚合:

aggregation_result = products.aggregate(pipeline)

Finally, run the following command in your shell to start your application:最后,在shell中运行以下命令以启动应用程序:

ruby agg_tutorial.rb
5

Interpret the aggregation results.解释聚合结果。

The aggregated result contains two documents. The documents represent products for which there were orders placed in 2020. Each document contains an orders array field that lists details about each order for that product:聚合结果包含两个文档。这些文件代表了2020年下订单的产品。每个文档都包含一个orders数组字段,其中列出了该产品的每个订单的详细信息:

{"name"=>"Asus Laptop", "variation"=>"Standard Display", "category"=>"ELECTRONICS", "orders"=>[{"customer_id"=>"elise_smith@myemail.com", "orderdate"=>2020-05-30 08:35:52 UTC, "value"=>431.43}, {"customer_id"=>"jjones@tepidmail.com", "orderdate"=>2020-12-26 08:55:46 UTC, "value"=>429.65}]}
{"name"=>"Morphy Richards Food Mixer", "variation"=>"Deluxe", "category"=>"KITCHENWARE", "orders"=>[{"customer_id"=>"oranieri@warmmail.com", "orderdate"=>2020-01-01 08:25:37 UTC, "value"=>63.13}]}

The result documents contain details from documents in the orders collection and the products collection, joined by the product names and variations.结果文档包含orders集合和orders集合中文档的详细信息,以及产品名称和变体。

Rust
1

Add a lookup stage to link the collections and import fields.添加查找阶段以链接集合和导入字段。

The first stage of the pipeline is a $lookup stage to join the orders collection to the products collection by two fields in each collection. The lookup stage contains an embedded pipeline to configure the join.管道的第一阶段是$lookup阶段,通过每个集合中的两个字段将orders集合连接到orders集合。查找阶段包含一个用于配置连接的嵌入式管道。

Within the embedded pipeline, add a $match stage to match the values of two fields on each side of the join. Note that the following code uses aliases for the name and variation fields set when creating the $lookup stage:在嵌入式管道中,添加一个$match阶段,以匹配连接两侧两个字段的值。请注意,以下代码在创建$lookup阶段时为namevariation字段设置了别名:

let mut embedded_pipeline = Vec::new();
embedded_pipeline.push(doc! {
"$match": {
"$expr": {
"$and": [
{ "$eq": ["$product_name", "$$prdname"] },
{ "$eq": ["$product_variation", "$$prdvartn"] }
]
}
}
});

Within the embedded pipeline, add another $match stage to match orders placed in 2020:在嵌入式管道中,添加另一个$match阶段来匹配2020年的订单:

embedded_pipeline.push(doc! {
"$match": {
"order_date": {
"$gte": DateTime::builder().year(2020).month(1).day(1).build().unwrap(),
"$lt": DateTime::builder().year(2021).month(1).day(1).build().unwrap()
}
}
});

Within the embedded pipeline, add an $unset stage to remove unneeded fields from the orders collection side of the join:在嵌入式管道中,添加一个$unset阶段,从连接的orders集合端删除不需要的字段:

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

After the embedded pipeline is completed, add the $lookup stage to the main aggregation pipeline. Configure this stage to store the processed lookup fields in an array field called orders:嵌入式管道完成后,将$lookup阶段添加到主聚合管道中。配置此阶段以将处理后的查找字段存储在名为orders的数组字段中:

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

Add a match stage for products ordered in 2020.为2020年订购的产品添加匹配阶段。

Next, add a $match stage to only show products for which there is at least one order in 2020, based on the orders array calculated in the previous step:接下来,根据上一步计算的orders数组,添加一个$match阶段,仅显示2020年至少有一个订单的产品:

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

Add an unset stage to remove unneeded fields.添加未设置的阶段以删除不需要的字段。

Finally, add an $unset stage. The $unset stage removes the _id and description fields from the result documents:最后,添加一个$unset阶段。$unset阶段从结果文档中删除_iddescription字段:

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

Run the aggregation pipeline.运行聚合管道。

Add the following code to the end of your application to perform the aggregation on the products collection:将以下代码添加到应用程序的末尾,以对products集合执行聚合:

let mut cursor = products.aggregate(pipeline).await?;

Finally, run the following command in your shell to start your application:最后,在shell中运行以下命令以启动应用程序:

cargo run
5

Interpret the aggregation results.解释聚合结果。

The aggregated result contains two documents. The documents represent products for which there were orders placed in 2020. Each document contains an orders array field that lists details about each order for that product:聚合结果包含两个文档。这些文件代表了2020年下订单的产品。每个文档都包含一个orders数组字段,其中列出了该产品的每个订单的详细信息:

Document({"name": String("Asus Laptop"), "variation": String("Standard Display"), "category": String("ELECTRONICS"),
"orders": Array([Document({"customer_id": String("elise_smith@myemail.com"), "order_date": DateTime(2020-05-30 8:35:52.0 +00:00:00),
"value": Double(431.42999267578125)}), Document({"customer_id": String("jjones@tepidmail.com"), "order_date":
DateTime(2020-12-26 8:55:46.0 +00:00:00), "value": Double(429.6499938964844)})])})

Document({"name": String("Morphy Richards Food Mixer"), "variation": String("Deluxe"), "category": String("KITCHENWARE"),
"orders": Array([Document({"customer_id": String("oranieri@warmmail.com"), "order_date": DateTime(2020-01-01 8:25:37.0 +00:00:00),
"value": Double(63.130001068115234)})])})

The result documents contain details from documents in the orders collection and the products collection, joined by the product names and variations.结果文档包含orders集合和products集合中文档的详细信息,以及产品名称和变体。

scala
1

Add a lookup stage to link the collections and import fields.添加查找阶段以链接集合和导入字段。

The first stage of the pipeline is a $lookup stage to join the orders collection to the products collection by two fields in each collection. The lookup stage contains an embedded pipeline to configure the join.管道的第一阶段是$lookup阶段,通过每个集合中的两个字段将orders集合连接到products集合。查找阶段包含一个用于配置连接的嵌入式管道。

Within the embedded pipeline, add a $match stage to match the values of two fields on each side of the join. 在嵌入式管道中,添加一个$match阶段,以匹配连接两侧两个字段的值。Note that the following code uses aliases for the name and variation fields set when creating the $lookup stage:请注意,以下代码在创建$lookup阶段时为namevariation字段设置了别名:

Aggregates.filter(
Filters.expr(
Filters.and(
Document("$eq" -> Seq("$product_name", "$$prdname")),
Document("$eq" -> Seq("$product_variation", "$$prdvartn"))
)
)
),

Within the embedded pipeline, add another $match stage to match orders placed in 2020:在嵌入式管道中,添加另一个$match阶段来匹配2020年的订单:

Aggregates.filter(
Filters.and(
Filters.gte("orderdate", dateFormat.parse("2020-01-01T00:00:00")),
Filters.lt("orderdate", dateFormat.parse("2021-01-01T00:00:00"))
)
),

Within the embedded pipeline, add an $unset stage to remove unneeded fields from the orders collection side of the join:在嵌入式管道中,添加一个$unset阶段,从连接的orders集合端删除不需要的字段:

Aggregates.unset("_id", "product_name", "product_variation"),

After the embedded pipeline is completed, add the $lookup stage to the main aggregation pipeline. Configure this stage to store the processed lookup fields in an array field called orders:嵌入式管道完成后,将$lookup阶段添加到主聚合管道中。配置此阶段以将处理后的查找字段存储在名为orders的数组字段中:

Aggregates.lookup(
"orders",
Seq(
Variable("prdname", "$name"),
Variable("prdvartn", "$variation"),
),
embeddedPipeline,
"orders"
),
2

Add a match stage for products ordered in 2020.为2020年订购的产品添加匹配阶段。

Next, add a $match stage to only show products for which there is at least one order in 2020, based on the orders array calculated in the previous step:接下来,根据上一步计算的orders数组,添加一个$match阶段,仅显示2020年至少有一个订单的产品:

Aggregates.filter(Filters.ne("orders", Seq())),
3

Add an unset stage to remove unneeded fields.添加未设置的阶段以删除不需要的字段。

Finally, add an $unset stage. The $unset stage removes the _id and description fields from the result documents:最后,添加一个$unset阶段。$unset阶段从结果文档中删除_iddescription字段:

Aggregates.unset("_id", "description")
4

Run the aggregation pipeline.运行聚合管道。

Add the following code to the end of your application to perform the aggregation on the products collection:将以下代码添加到应用程序的末尾,以对products集合执行聚合:

products.aggregate(pipeline)
.subscribe(
(doc: Document) => println(doc.toJson()),
(e: Throwable) => println(s"Error: $e"),
)

Finally, run the application in your IDE.最后,在IDE中运行应用程序。

5

Interpret the aggregation results.解释聚合结果。

The aggregated result contains two documents. The documents represent products for which there were orders placed in 2020. Each document contains an orders array field that lists details about each order for that product:聚合结果包含两个文档。这些文件代表了2020年下订单的产品。每个文档都包含一个orders数组字段,其中列出了该产品的每个订单的详细信息:

{"name": "Asus Laptop", "variation": "Standard Display", "category": "ELECTRONICS", "orders": [{"customer_id": "elise_smith@myemail.com", "orderdate": {"$date": "2020-05-30T12:35:52Z"}, "value": 431.43}, {"customer_id": "jjones@tepidmail.com", "orderdate": {"$date": "2020-12-26T13:55:46Z"}, "value": 429.65}]}
{"name": "Morphy Richards Food Mixer", "variation": "Deluxe", "category": "KITCHENWARE", "orders": [{"customer_id": "oranieri@warmmail.com", "orderdate": {"$date": "2020-01-01T13:25:37Z"}, "value": 63.13}]}

The result documents contain details from documents in the orders collection and the products collection, joined by the product names and variations.结果文档包含orders集合和products集合中文档的详细信息,以及产品名称和变体。