Disclaimer
Lees, voordat u de rest van het antwoord leest, eerst https://docs. mongodb.com/manual/core/aggregation-pipeline-limits/ Het resulterende document in de vraag zal naar verwachting een array bevatten van alle documenten die tot een bepaalde leeftijdsgroep behoren.De grootte van die array mag niet groter zijn dan 16 MB , dus de onderstaande code werkt alleen voor zeer kleine verzamelingen van kleine documenten.
De code:
db.collection.aggregate([
{ $sort: { age: 1 } },
{ $group: {
_id: null,
ages: { $push: "$age" }
} },
{ $addFields: {
ranges: { $reduce: {
input: { $range: [ 1, { $size: "$ages" }, 1 ] },
initialValue: [ [ { $arrayElemAt: [ "$ages", 0 ] } ] ],
in: { $cond: {
if: { $gt: [
{ $subtract: [ { $arrayElemAt: [ "$ages", "$$this" ] }, { $arrayElemAt: [ "$ages", { $subtract: [ "$$this", 1 ] } ] } ] },
2
] },
then: { $concatArrays: [ "$$value", [ [ { $arrayElemAt: [ "$ages", "$$this" ] } ] ] ] },
else: { $concatArrays: [
{ $slice: [ "$$value" , { $subtract: [ { $size: "$$value" }, 1 ] } ] },
[ { $concatArrays: [
{ $arrayElemAt: [ { $slice: [ "$$value" , -1 ] }, 0 ] } ,
[ { $arrayElemAt: [ "$ages", "$$this" ] } ]
] } ]
] }
} }
} }
} },
{ $unwind: "$ranges" },
{ $lookup: {
from: "collection",
localField: "ranges",
foreignField: "age",
as: "group"
} },
{ $project: { _id: 0, group: 1 } }
])
Het deel dat misschien wat uitleg nodig heeft, is hoe je leeftijdsgroepen berekent.
Daarvoor krijgen we alle leeftijden met behulp van $group in een enkele array en vervolgens $addFields "bereiken" - een 2D-array van leeftijdsgroepen met een kloof tussen de oudste persoon in een jongere groep en een jongste persoon in de oudere groep is groter dan 2 jaar.
De array wordt berekend met behulp van $reduce van een $range reeks indexen van alle leeftijden behalve eerst, die naar de beginwaarde gaat.
De reduce-expressie is een $cond die het verschil tussen huidige en vorige berekent ($subtract ) element van de array van alle leeftijden.
Als deze groter is dan 2, wordt een nieuwe leeftijdsgroep toegevoegd met behulp van $concatArrays . Anders wordt de leeftijd toegevoegd aan de oudste groep met behulp van $slice om naar de laatste groep in de reeksen te pushen en $setUnion om duplicaten te verwijderen.
Wanneer de leeftijdsgroepen worden berekend, gebruiken we $lookup dezelfde collectie op leeftijd om ze te groeperen in de "groep"-array.