文档首页 → 开发应用程序 → Python 驱动程序 → PyMongo
多字段连接
简介
在本教程中,您可以通过完成和运行一个示例应用程序来学习如何使用 PyMongo 构建聚合管道,在一个集合上执行聚合,并通过打印结果来打印结果。
此聚合执行多字段连接。当您在两个集合的文档中找到多个对应字段时,就会发生多字段连接。聚合将这些文档根据字段值进行匹配,并将两个集合的信息合并到一个文档中。
提示
一对一连接
一对一连接是多字段连接的一种形式。当您执行一对一连接时,您从一个与连接另一侧多个文档的字段值匹配的字段中选择一个字段。要了解更多关于这些数据关系的信息,请参阅维基百科上有关一对一(数据模型) 和 多对多(数据模型)。
聚合任务概要
本教程演示了如何将描述产品信息的集合中的数据与描述客户订单的另一个集合中的数据相结合。结果显示了一个2020年订购的产品列表,其中还包含了每个订单的详细信息。
本例使用了两个集合
products
,其中包含描述商店销售产品的文档orders
,其中包含描述商店产品单个订单的文档
一个订单只能包含一个产品,因此聚合使用多字段连接将产品文档与代表该产品订单的文档相匹配。集合通过products
集合中文档的name
和variation
字段与orders
集合中文档的product_name
和product_variation
字段进行连接。
开始之前
在开始此教程之前,请完成聚合模板应用程序说明,以设置一个可工作的Python应用程序。
设置应用程序后,通过将以下代码添加到应用程序中访问products
和orders
集合
products_coll = agg_db["products"] orders_coll = agg_db["orders"]
删除任何现有数据,并将以下代码中的示例数据插入到 products
集合中
products_coll.delete_many({}) 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)
删除任何现有数据,并将以下代码中的示例数据插入到 orders
集合中
orders_coll.delete_many({}) 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)
教程
添加一个查找阶段来链接集合并导入字段
管道的第一个阶段是一个 $lookup 阶段,用于通过每个集合中的两个字段将 orders
集合与 products
集合进行连接。查找阶段包含一个嵌入的管道来配置连接。
在嵌入的管道中,添加一个 $match 阶段来匹配连接两侧两个字段的值。注意,以下代码使用在创建 $lookup
阶段时设置的 name
和 variation
字段的别名
embedded_pl = [ { "$match": { "$expr": { "$and": [ {"$eq": ["$product_name", "$$prdname"]}, {"$eq": ["$product_variation", "$$prdvartn"]} ] } } } ]
在嵌入的管道中,添加另一个 $match 阶段来匹配2020年下订单的订单
embedded_pl.append({ "$match": { "orderdate": { "$gte": datetime(2020, 1, 1, 0, 0, 0), "$lt": datetime(2021, 1, 1, 0, 0, 0) } } })
在嵌入的管道中,添加一个 $unset 阶段来从连接的 orders
集合侧删除不需要的字段
embedded_pl.append({ "$unset": ["_id", "product_name", "product_variation"] })
嵌入的管道完成后,将 $lookup
阶段添加到主聚合管道中。配置此阶段将处理后的查找字段存储在名为 orders
的数组字段中
pipeline.append({ "$lookup": { "from": "orders", "let": { "prdname": "$name", "prdvartn": "$variation" }, "pipeline": embedded_pl, "as": "orders" } })
添加一个匹配阶段以匹配2020年订购的产品
接下来,添加一个 $match 阶段,仅显示至少有一个2020年订单的产品,基于上一步中计算的 orders
数组
pipeline.append({ "$match": { "orders": {"$ne": []} } })
添加一个unset阶段来删除不需要的字段
最后,添加一个 $unset 阶段。该 $unset
阶段从结果文档中删除了 _id
和 description
字段
pipeline.append({ "$unset": ["_id", "description"] })
解释结果
聚合结果包含两个文档。这些文档代表在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 } ] }
结果文档包含来自orders
集合和products
集合的文档的详细信息,通过产品名称和变体进行连接。
要查看本教程的完整代码,请参阅GitHub上的完成的多字段连接应用程序。