I have documents that look like:
[
{
value: 'Apple',
createdAt: '2021-12-09T20:15:26.421 00:00',
},
{
value: 'Blueberry',
createdAt: '2021-12-09T20:45:26.421 00:00',
},
{
value: 'Cranberry',
createdAt: '2021-12-09T21:30:26.421 00:00',
},
{
value: 'Durian',
createdAt: '2022-01-24T20:15:26.421 00:00',
},
{
value: 'Elderberry',
createdAt: '2022-01-24T20:45:26.421 00:00',
},
]
I'd like to do an aggregation where I get the oldest document, with the caveat that if another document was created within an hour, it invalidates the first document and I actually want to grab that one instead. For example, in the above I would like to return Cranberry. Initially pick Apple, but since Blueberry comes within an hour, move to that one, and since Cranberry comes within an hour of Blueberry, select Cranberry.
CodePudding user response:
You can do the followings in an aggregation pipeline:
$sortbycreatedAt$limitto get the oldest document$lookupto get all the documents withcreatedAtbehind the current document$reduceto loop the result array; update the accumulator/result only if the current entry is within 1 hour
db.collection.aggregate([
{
$sort: {
createdAt: 1
}
},
{
$limit: 1
},
{
"$lookup": {
"from": "collection",
let: {
current: "$createdAt"
},
pipeline: [
{
$match: {
$expr: {
$gte: [
"$createdAt",
"$$current"
]
}
}
}
],
"as": "within"
}
},
{
"$addFields": {
"within": {
"$reduce": {
"input": "$within",
"initialValue": null,
"in": {
"$cond": {
"if": {
$or: [
{
$eq: [
"$$value",
null
]
},
{
$lte: [
{
"$subtract": [
"$$this.createdAt",
"$$value.createdAt"
]
},
3600000
]
}
]
},
"then": "$$this",
"else": "$$value"
}
}
}
}
}
}
])
Here is the Mongo playground for your reference.
