MongoDB 最全面的增强版本 4.4 新特性之 $unionWith 使用

本文介绍了MongoDB 4.4新引入的$unionWith操作符,它允许用户将多个集合的数据聚合到一起进行查询和过滤,类似于SQL的UNION ALL。通过示例展示了如何统计不同集合中商品的总数量,并进一步解释了如何根据条件(如早餐、中餐、晚餐)合并数据并进行统计,以获取每天每个地点的餐食数量。这种方法简化了以往需要通过代码实现的复杂过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在多表联合查询能力上,4.4 之前只提供了一个 $lookup stage 用于实现类似于 SQL 中的「left outer join」功能,在 4.4 中新增的 $unionWith stage 又提供了类似 SQL 中的「union all」功能,用户把两个集合中的数据聚合到一个结果集中,然后做指定的查询和过滤。区别于 $lookup stage 的是, $unionWith stage 支持分片集合。当在 Aggregate Pipeline 中使用了多个 $unionWith stage 的时候,可以对多个集合数据做聚合,使用方式如下:

{ $unionWith: { coll: "<collection>", pipeline: [ <stage1>, ... ] } }

假设我们现在有这样的数据:

db.orders_april.insertMany([
  { _id:1, item: "A", quantity: 100 },
  { _id:2, item: "B", quantity: 30 },
]);
db.orders_may.insertMany([
  { _id:1, item: "C", quantity: 20 },
  { _id:2, item: "A", quantity: 50 },
]);
db.orders_june.insertMany([
  { _id:1, item: "C", quantity: 100 },
  { _id:2, item: "D", quantity: 10 },
]);

现在我想知道orders_may,orders_june,orders_april这三个集合中,不同产品item的数量quantity总和是多少?

如果是以前,只能用代码来实现;现在可以:

db.orders_april.aggregate( [
   { $unionWith: "orders_may" },
   { $unionWith: "orders_june" },
   { $group: { _id: "$item", total: { $sum: "$quantity" } } },
   { $sort: { total: -1 }}
] )

结果:

/* 1 */
{
    "_id" : "A",
    "total" : 150.0
}

/* 2 */
{
    "_id" : "C",
    "total" : 120.0
}

/* 3 */
{
    "_id" : "B",
    "total" : 30.0
}

/* 4 */
{
    "_id" : "D",
    "total" : 10.0
}

假设我们现在有这样的数据(site:1早餐,2中餐,3晚餐;placeId:地点ID;cateringDate:时间):

在这里插入图片描述
现在我想知道每天每个地方的早餐数,中餐数,晚餐数(即在一个集合中根据条件将多条数据合并成一条进行数据统计)?

db.catering.aggregate([ 
            {
                "$unionWith" : {
                    "coll" : "catering",
                    "pipeline" : [ 
                        {
                        	//筛选条件早餐
                            "$match" : {
                                "site" : 1.0
                            }
                        }, 
                        {
                            "$addFields" : {
                                "breakfast" : 1.0,//早餐1份
                                "lunch" : 0.0,
                                "dinner" : 0.0
                            }
                        }
                    ]
                }
            }, 
            {
                "$unionWith" : {
                    "coll" : "catering",
                    "pipeline" : [ 
                        {
                        	//筛选条件中餐
                            "$match" : {
                                "site" : 2.0
                            }
                        }, 
                        {
                            "$addFields" : {
                                "breakfast" : 0.0,
                                "lunch" : 1.0,//中餐1份
                                "dinner" : 0.0
                            }
                        }
                    ]
                }
            }, 
            {
                "$unionWith" : {
                    "coll" : "catering",
                    "pipeline" : [ 
                        {
                        	//筛选条件晚餐
                            "$match" : {
                                "site" : 3.0
                            }
                        }, 
                        {
                            "$addFields" : {
                                "breakfast" : 0.0,
                                "lunch" : 0.0,
                                "dinner" : 1.0//晚餐1份
                            }
                        }
                    ]
                }
            }, 
            {
                "$addFields" : {
                	//日期格式化,因为是UTC时间所以+8小时
                    "cateringDateString" : {
                        "$dateToString" : {
                            "format" : "%Y-%m-%d",
                            "date" : "$cateringDate",
                            "timezone" : "+08:00"
                        }
                    }
                }
            }, 
            {
                "$group" : {
                	//按照日期地点分组
                    "_id" : {
                        "date" : "$cateringDateString",
                        "placeId" : "$placeId"
                    },
                    //计算所有早餐
                    "totalBreakfast" : {
                        "$sum" : "$breakfast"
                    },
                    //计算所有中餐
                    "totalLunch" : {
                        "$sum" : "$lunch"
                    },
                    //计算所有晚餐
                    "totalDinner" : {
                        "$sum" : "$dinner"
                    }
                }
            }, 
            {
                "$project" : {
                    "date" : "$_id.date",
                    "placeId" : "$_id.placeId",
                    "totalBreakfast" : 1.0,
                    "totalLunch" : 1.0,
                    "totalDinner" : 1.0,
                    "_id" : 0.0
                }
            }, 
            {
                "$sort" : {
                    "date" : 1.0
                }
            } 
            
        ])

结果:

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值