我的付款收款包含条纹费用返回的数据。 “created”属性是一个时间戳(unix epoch,以秒为单位)。我有一个查询,可以查找日期范围内给定会员ID的成功费用,并汇总付款金额:
// start of the day for Jan 1, 2017 (unix epoch)
var jan1 = 1483250400
// end of the day for May 1, 2017 (unix epoch)
var may1 = 1502000000
var pipeline = [
{
$match: {
// Member id
_id: ObjectId("597ceea6122ccfda71d011be"),
}
},
{
$project: {
_id: 0,
payments: {
$filter: {
input: "$payments",
as: "payment",
cond: {
$and: [
{ $gte: ["$$payment.created", jan1] },
{ $lte: ["$$payment.created", may1] },
{ $eq: ["$$payment.status", "succeeded"] }
]
}
}
}
}
},
{
$project: {
paid: {
$sum: "$payments.amount"
}
}
}
]
db.members.aggregate(pipeline).pretty()
它以下列格式返回数据:
{
"paid" : 190000
}
问题是我还有其他几个我想查询的日期范围:
我可以随时单独执行每个查询,但我宁愿一次完成所有查询。我已尝试使用$bucket
,但不支持使用相同的查询1月1日的下限阈值。
我希望将付费号码与每个日期范围相关联。 理想情况下,输出看起来像这样:
{
"May 1": 190000,
"July 15": 240000,
"Sept 15": 250000,
"Dec 31": 255000
}
答案 0 :(得分:1)
这样做的一种方式是:
var jan1 = 1483250400;
var may2 = 1493683200;
var jul16 = 1500163200;
var sep16 = 1505520000;
var jan1NextYear = 1514764800;
db.collection.aggregate([
{
// I omit your match stage here but you will need it, obviously
$project: {
payments: {
$map: {
input: "$payments",
as: "payment",
in: {
janToMay: {
$cond: {
if: {
$and: [
{ $gte: ["$$payment.created", jan1] },
{ $lt: ["$$payment.created", may2] }
]
},
then: "$$payment.amount",
else: null
}
},
janToJul: {
$cond: {
if: {
$and: [
{ $gte: ["$$payment.created", jan1] },
{ $lt: ["$$payment.created", jul16] }
]
},
then: "$$payment.amount",
else: null
}
},
janToSep: {
$cond: {
if: {
$and: [
{ $gte: ["$$payment.created", jan1] },
{ $lt: ["$$payment.created", sep16] }
]
},
then: "$$payment.amount",
else: null
}
},
janToDec: {
$cond: {
if: {
$and: [
{ $gte: ["$$payment.created", jan1] },
{ $lt: ["$$payment.created", jan1NextYear] }
]
},
then: "$$payment.amount",
else: null
}
}
}
}
}
}
},
{
$project: {
"May 1": {
$sum: "$payments.janToMay"
},
"Jul 15": {
$sum: "$payments.janToJul"
},
"Sep 15": {
$sum: "$payments.janToSep"
},
"Dec 31": {
$sum: "$payments.janToDec"
},
}
}
])
这是一个非常通用的解决方案。但是,在您的特定情况下,您可能希望将所有过滤器的公共部分提取到单独的过滤器步骤,如下所示:
var jan1 = 1483250400;
var may1 = 1493596800;
var jul16 = 1500163200;
var sep16 = 1505520000;
var jan1NextYear = 1514764800;
db.collection.aggregate([
{
// I omit your match stage here but you will need it, obviously
$project: {
payments: {
$map: {
input: {
$filter: { // here we drop all the elements that all of the below filters would drop anyway
input: "$payments",
as: "payment",
cond: {
$gte: ["$$payment.created", jan1],
}
}
},
as: "payment",
in: {
janToMay: {
$cond: {
if: {
$lt: ["$$payment.created", may1]
},
then: "$$payment.amount",
else: null
}
},
janToJul: {
$cond: {
if: {
$lt: ["$$payment.created", jul16]
},
then: "$$payment.amount",
else: null
}
},
janToSep: {
$cond: {
if: {
$lt: ["$$payment.created", sep16]
},
then: "$$payment.amount",
else: null
}
},
janToDec: {
$cond: {
if: {
$lt: ["$$payment.created", jan1NextYear]
},
then: "$$payment.amount",
else: null
}
}
}
}
}
}
}
// the final project stage stays identical to the one in the above example
])