• 1000 1003 *
{
"day": string
"newUsers" : number,
"DateTimes" : Array<{day: number, month: number, year: number, users: number, percentage: number}>
}
С уже отсортированным массивом DateTime
, поэтому для R_1
вы должны использовать DateTime[0].percentage
для процента пользователей на этот день.
db.collection.aggregate([
{
$group: {
_id: {
day: {$dayOfMonth: "$Registered"},
month: {$month: "$Registered"},
year: {$year: "$Registered"},
dateTimeDay: {$dayOfMonth: "$DateTime"},
dateTimeMonth: {$month: "$DateTime"},
dateTimeYear: {$year: "$DateTime"}
},
users: {$addToSet: "$PlayerId"}
}
},
{
$group: {
_id: {day: "$_id.day", month: "$_id.month", year: "$_id.year"},
totalUsers: {$addToSet: "$users"},
DateTimes: {
$push: {
day: "$_id.dateTimeDay",
month: "$_id.dateTimeMonth",
year: "$_id.dateTimeYear",
users: {$size: "$users"}
}
}
}
},
{
$addFields: {
R1_to_R7: {
$map: {
input: [1, 2, 3, 4, 5, 6, 7],
as: "input",
in: {
$cond: [
{$setIsSubset: [["$_id.month"], [1, 3, 5, 7, 8, 10, 12]]},
{
$cond: [
{
$and: [
{$lt: [{$mod: [{$sum: ["$_id.day", "$$input"]}, 32]}, 7]},
{$gt: ["$_id.day", 20]}
]
},
{
day: {$sum: [{$mod: [{$sum: ["$_id.day", "$$input"]}, 32]}, 1]},
month: {
$cond: [
{$eq: [{$mod: [{$sum: ["$_id.month", 1]}, 13]}, 0]},
1,
{$sum: ["$_id.month", 1]},
]
},
year: {
$cond: [
{$eq: [{$mod: [{$sum: ["$_id.month", 1]}, 13]}, 0]},
{$sum: ["$_id.year", 1]},
"$_id.year"
]
}
},
{
day: {$mod: [{$sum: ["$_id.day", "$$input"]}, 32]},
month: "$_id.month",
year: "$_id.year"
}
]
},
{
$cond: [
{
$eq: ["$_id.month", 2]
},
{
$cond: [
{
$and: [
{$lt: [{$mod: [{$sum: ["$_id.day", "$$input"]}, 29]}, 7]},
{$gt: ["$_id.day", 20]}
]
},
{
day: {$sum: [{$mod: [{$sum: ["$_id.day", "$$input"]}, 29]}, 1]},
month: 3,
year: "$_id.year",
},
{
day: {$mod: [{$sum: ["$_id.day", "$$input"]}, 29]},
month: "$_id.month",
year: "$_id.year"
}
]
},
{
$cond: [
{
$and: [
{$lt: [{$mod: [{$sum: ["$_id.day", "$$input"]}, 31]}, 7]},
{$gt: ["$_id.day", 20]}
]
},
{
day: {$sum: [{$mod: [{$sum: ["$_id.day", "$$input"]}, 31]}, 1]},
month: {$sum: ["$_id.month", 1]},
year: "$_id.year",
},
{
day: {$mod: [{$sum: ["$_id.day", "$$input"]}, 31]},
month: "$_id,month",
year: "$_id.year"
}
]
}
]
}
]
}
}
}
}
},
{
$project: {
_id: 0,
day: {$concat: [{$toString: "$_id.day"}, "/", {$toString: "$_id.month"}, "/", {$toString: "$_id.year"}]},
newUsers: {
$size: {
$reduce: {
input: "$totalUsers",
initialValue: [],
in: {$setUnion: ["$$value", "$$this"]}
}
}
},
DateTimes: {
$map: {
input: "$R1_to_R7",
as: "next_day",
in: {
$cond: [
{
$gt: [
{
$size: {
$filter: {
input: "$DateTimes",
as: "dateTime",
cond: {
$eq: [{
day: "$$dateTime.day",
month: "$$dateTime.month",
year: "$$dateTime.year"
}, "$$next_day"]
}
}
}
},
0
]
},
{
$arrayElemAt: [
{
$filter: {
input: "$DateTimes",
as: "dateTime",
cond: {
$eq: [{
day: "$$dateTime.day",
month: "$$dateTime.month",
year: "$$dateTime.year"
}, "$$next_day"]
}
}
},
0
]
},
{
$mergeObjects: ["$$next_day", {users: 0}]
}
]
}
}
}
}
},
{
$project: {
day: 1,
newUsers: 1,
DateTimes: {
$map: {
input: "$DateTimes",
as: "datetime",
in: {
$mergeObjects: [
"$$datetime",
{percentage: {$multiply: [100, {$divide: ["$$datetime.users", "$newUsers"]}]}}
]
}
}
}
}
}
])
С этим вне способ Еще 2 вещи, которые следует учитывать:
- Первый этап
$addFields
используется для «добавления» следующих 7 дней. это довольно сложно сделать Mon go в данном контексте. если бы вы могли сделать это в коде, было бы лучше, поскольку существует много дублирования. - Как видите, мне пришлось изменить значения
day
, month
и year
на следующие 7 дней, если регистрация была, скажем, 31-го числа. НО я не учел разрыв в годах. если вы хотите сохранить его таким образом и чтобы он был стабильным, вы должны добавить проверку промежуточного года ($mod
должен работать нормально, так как это каждые 4 года.) к условию с 2
месяцем (февраль).