Ecco una query di aggregazione che restituisce l'output previsto. Alcuni documenti di esempio:
[
{ created_at: "2020-04-04T17:02:07.832Z", productId: 1 },
{ created_at: "2020-02-01T17:02:07.832Z", productId: 1 },
{ created_at: "2020-02-19T17:02:07.832Z", productId: 1 },
{ created_at: "2019-05-22T17:02:07.832Z", productId: 1 },
{ created_at: "2020-01-15T17:02:07.832Z", productId: 1 },
{ created_at: "2020-01-30T17:02:07.832Z", productId: 2 }, // not selected
{ created_at: "2019-03-15T17:02:07.832Z", productId: 1 } // not selected
]
Le variabili di input e l'aggregazione:
let TODAY = "2020-04-06T23:59:59"
let YEAR_BEFORE = "2019-04-07T00:00:00"
let req = { params: { productId: 1 } }
const monthsArray = [ 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December' ]
db.sales.aggregate( [
{
$match: {
productId: req.params.productId,
created_at: { $gte: YEAR_BEFORE, $lte: TODAY }
}
},
{
$group: {
_id: { "year_month": { $substrCP: [ "$created_at", 0, 7 ] } },
count: { $sum: 1 }
}
},
{
$sort: { "_id.year_month": 1 }
},
{
$project: {
_id: 0,
count: 1,
month_year: {
$concat: [
{ $arrayElemAt: [ monthsArray, { $subtract: [ { $toInt: { $substrCP: [ "$_id.year_month", 5, 2 ] } }, 1 ] } ] },
"-",
{ $substrCP: [ "$_id.year_month", 0, 4 ] }
]
}
}
},
{
$group: {
_id: null,
data: { $push: { k: "$month_year", v: "$count" } }
}
},
{
$project: {
data: { $arrayToObject: "$data" },
_id: 0
}
}
] )
L'uscita:
{
"data" : {
"May-2019" : 1,
"January-2020" : 1,
"February-2020" : 2,
"April-2020" : 1
}
}
Ecco l'aggregazione aggiornata .
Nota le seguenti modifiche:(1) nuove costanti FIRST_MONTH e LAST_MONTH, (2) modificato monthsArray
nome della variabile a MONTHS_ARRAY, (3) aggiunte 3 nuove fasi della pipeline.
Le prime due fasi della pipeline (nuove) creano un modello con tutti i mesi (che copre l'intervallo di date da e verso l'input). La terza nuova fase unisce il modello con i dati di output derivati dall'aggregazione precedente.
const FIRST_MONTH = 1
const LAST_MONTH = 12
const MONTHS_ARRAY = [ 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December' ]
let TODAY = "2020-04-06T23:59:59"
let YEAR_BEFORE = "2019-04-07T00:00:00"
db.sales.aggregate( [
{
$match: {
productId: req.params.productId,
created_at: { $gte: YEAR_BEFORE, $lte: TODAY }
}
},
{
$group: {
_id: { "year_month": { $substrCP: [ "$created_at", 0, 7 ] } },
count: { $sum: 1 }
}
},
{
$sort: { "_id.year_month": 1 }
},
{
$project: {
_id: 0,
count: 1,
month_year: {
$concat: [
{ $arrayElemAt: [ monthsArray, { $subtract: [ { $toInt: { $substrCP: [ "$_id.year_month", 5, 2 ] } }, 1 ] } ] },
"-",
{ $substrCP: [ "$_id.year_month", 0, 4 ] }
]
}
}
},
{
$group: {
_id: null,
data: { $push: { k: "$month_year", v: "$count" } }
}
},
{
$addFields: {
start_year: { $substrCP: [ YEAR_BEFORE, 0, 4 ] },
end_year: { $substrCP: [ TODAY, 0, 4 ] },
months1: { $range: [ { $toInt: { $substrCP: [ YEAR_BEFORE, 5, 2 ] } }, { $add: [ LAST_MONTH, 1 ] } ] },
months2: { $range: [ FIRST_MONTH, { $add: [ { $toInt: { $substrCP: [ TODAY, 5, 2 ] } }, 1 ] } ] }
}
},
{
$addFields: {
template_data: {
$concatArrays: [
{ $map: {
input: "$months1", as: "m1",
in: {
count: 0,
month_year: {
$concat: [ { $arrayElemAt: [ MONTHS_ARRAY, { $subtract: [ "$$m1", 1 ] } ] }, "-", "$start_year" ]
}
}
} },
{ $map: {
input: "$months2", as: "m2",
in: {
count: 0,
month_year: {
$concat: [ { $arrayElemAt: [ MONTHS_ARRAY, { $subtract: [ "$$m2", 1 ] } ] }, "-", "$end_year" ]
}
}
} }
]
}
}
},
{
$addFields: {
data: {
$map: {
input: "$template_data", as: "t",
in: {
k: "$$t.month_year",
v: {
$reduce: {
input: "$data", initialValue: 0,
in: {
$cond: [ { $eq: [ "$$t.month_year", "$$this.k"] },
{ $add: [ "$$this.v", "$$value" ] },
{ $add: [ 0, "$$value" ] }
]
}
}
}
}
}
}
}
},
{
$project: {
data: { $arrayToObject: "$data" },
_id: 0
}
}
] )
L'output:
{
"data" : {
"April-2019" : 0,
"May-2019" : 1,
"June-2019" : 0,
"July-2019" : 0,
"August-2019" : 0,
"September-2019" : 0,
"October-2019" : 0,
"November-2019" : 0,
"December-2019" : 0,
"January-2020" : 1,
"February-2020" : 2,
"March-2020" : 0,
"April-2020" : 1
}
}