Это немного утомительное решение.
Пояснение
Я предполагаю, activity.type
не повторяется внутри X
мин распада Я предполагаю start_timestamp
и end_timestamp
as is
(не игнорируйте секунды: миллисекунды)
- Мы рассчитываем минимальные / максимальные даты из
start_timestamp
и end_timestamp
- Мы вычисляем, сколько
15 min breaks
находится между минимальными / максимальными датами - Мы создаем
from
и to
переменных, которые включают X
минимальный разбив по минимальным / максимальным датам - Для каждый
from
и to
, мы фильтруем действия - . После фильтрации мы рассчитываем потерянное время, учитывая
from
и to
и start_timestamp
и end_timestamp
даты
db.collection.aggregate([
{
$project: {
root: "$$ROOT",
duration: {
$toInt: 15
},
"start": {
$reduce: {
"input": "$activity",
initialValue: ISODate("2100-01-01"),
in: {
$min: [
"$$value",
"$$this.start_timestamp",
"$$this.end_timestamp"
]
}
}
},
"end": {
$reduce: {
"input": "$activity",
initialValue: ISODate("1970-01-01"),
in: {
$max: [
"$$value",
"$$this.start_timestamp",
"$$this.end_timestamp"
]
}
}
}
}
},
{
$addFields: {
interval: {
$range: [
0,
{
$round: {
$divide: [
{
$toLong: {
$subtract: [
"$end",
"$start"
]
}
},
{
$multiply: [
"$duration",
60,
1000
]
}
]
}
},
1
]
}
}
},
{
$unwind: "$interval"
},
{
$addFields: {
from: {
$add: [
"$start",
{
$multiply: [
"$interval",
{
$multiply: [
"$duration",
60,
1000
]
}
]
}
]
},
to: {
$min: [
"$end",
{
$add: [
"$start",
{
$multiply: [
{
$add: [
"$interval",
1
]
},
{
$multiply: [
"$duration",
60,
1000
]
}
]
}
]
}
]
},
activity: "$root.activity"
}
},
{
$addFields: {
activity: {
$filter: {
input: "$activity",
cond: {
$or: [
{
$and: [
{
$gte: [
"$$this.start_timestamp",
"$from"
]
},
{
$lte: [
"$$this.end_timestamp",
"$to"
]
}
]
},
{
$and: [
{
$lte: [
"$$this.start_timestamp",
"$to"
]
},
{
$gte: [
"$$this.end_timestamp",
"$from"
]
}
]
}
]
}
}
}
}
},
{
$project: {
_id: {
$concat: [
{
$toString: "$from"
},
" to ",
{
$toString: "$to"
}
]
},
name: "$root.name",
duration: {
$concat: [
{
$toString: "$duration"
},
" min"
]
},
"brake-up": {
$map: {
input: "$activity",
in: {
k: "$$this.type",
v: {
$round: {
$divide: [
{
"$subtract": [
{
$min: [
"$$this.end_timestamp",
"$to"
]
},
{
$max: [
"$$this.start_timestamp",
"$from"
]
}
]
},
{
$multiply: [
60,
1000
]
}
]
}
}
}
}
}
}
},
{
$unwind: "$brake-up"
},
{
$group: {
_id: {
_id: "$_id",
duration: "$duration",
name: "$name",
"brake-up-k": "$brake-up.k"
},
"brake-up-v": {
$sum: "$brake-up.v"
}
}
},
{
$group: {
_id: {
_id: "$_id._id",
duration: "$_id.duration",
name: "$_id.name"
},
"brake-up": {
$push: {
k: "$_id.brake-up-k",
v: {
$concat: [
{
$toString: "$brake-up-v"
},
" min"
]
}
}
}
}
},
{
$project: {
_id: "$_id._id",
name: "$_id.name",
duration: "$_id.duration",
"brake-up": {
$arrayToObject: "$brake-up"
}
}
},
{
$sort: {
_id: 1
}
}
])
MongoPlayground