我在mongodb上有一堆这种格式的记录
[
{_id: 1, date:'2023-07-28',sales:1,ad_id:1,status: 'Active'},
{_id: 2 , date:'2023-07-29',sales:2,ad_id:1,status: 'Active'},
{_id: 3, date: '2023-07-30',sales: 4,ad_id:1,status: 'Paused'},
{_id: 4, date: '2023-07-30',sales: 4,ad_id:2,status: 'Paused'},
]
现在,如果我想要从日期
2023-07-28
到 2023-07-29
的数据。我想要对销售额进行求和,但我想要最新记录的状态,即 2023-07-30
。所以最后我想要的结果是这样的
{'ad_id': 1, sales: 3, status: 'Paused'}
。
在 mysql 上会是这样的
with ad as (
SELECT sum(sales) as totalSales,ad_id from table_name
where date >= '2023-07-28' and date <= '2023-07-29'
group by ad_id
)
SELECT * from ad left join (
SELECT id,ad_id,status from table_name where id in (
select max(id) from table_name group by ad_id
)
) t on t.ad_id = ad.ad_id
这是您可以做到的一种方法。
db.collection.aggregate([
{
"$group": {
"_id": "$ad_id",
"statusObj": {
// get the last status
"$max": {
"date": "$date",
"_id": "$_id",
"status": "$status"
}
},
"sales": {
"$sum": {
// only sum sales in date range
"$cond": [
{"$and": [
{"$gte": ["$date", "2023-07-28"]},
{"$lte": ["$date", "2023-07-29"]}
]
},
"$sales",
0
]
}
}
}
},
{ // output desired fields
"$project": {
"_id": 0,
"ad_id": "$_id",
"sales": 1,
"status": "$statusObj.status"
}
}
])
在 mongoplayground.net 上尝试一下。
我将总结以下代码的作用:
facet
创建两个差异聚合,分别命名为 salesSum
和 recentStatus
salesSum
中,我们筛选日期,然后对 ad_id
列进行分组,然后从中提取 sales
信息recentStatus
中,我们对 ad_id
进行分组,并通过分组计算出 _id
列的最大值,然后在 maxId
上对其进行过滤,以使用 status
获取最近的 $push: "$$ROOT"
salesSum
在
recentStatus
和
$unwind
ad_id
代码:
db.collection.aggregate([
{
$facet: {
salesSum: [
{
// filters on date
$match: {
date: {
$gte: "2023-07-28",
$lte: "2023-07-29",
},
},
},
{
// groups on ad_id and gets sum of sales
$group: {
_id: "$ad_id",
sales: {
$sum: "$sales",
},
},
},
{
// select specific cols
$project: {
_id: 0,
ad_id: "$_id",
sales: 1,
},
},
],
recentStatus: [
{
// group on ad_id, get maxId
// assuming maximum ID is associated with latest entry
$group: {
_id: "$ad_id",
maxId: {
$max: "$_id",
},
// pushes all related data which have ad_id values as the same as grouped value
items: {
$push: "$$ROOT",
},
},
},
{
$unwind: "$items",
},
{
// filter items based on maxId
$match: {
$expr: {
$eq: [
"$maxId",
"$items._id"
],
},
},
},
{
$project: {
_id: 0,
ad_id: "$_id",
status: "$items.status",
},
},
],
},
},
{
$unwind: "$salesSum",
},
{
$unwind: "$recentStatus",
},
{
$match: {
$expr: {
$eq: [
"$salesSum.ad_id",
"$recentStatus.ad_id"
],
},
},
},
{
$project: {
ad_id: "$salesSum.ad_id",
sales: "$salesSum.sales",
status: "$recentStatus.status",
},
},
])