免責事項
残りの回答を読む前に、 https://docsをお読みください。 mongodb.com/manual/core/aggregation-pipeline-limits/ 問題の結果のドキュメントには、特定の年齢層に属するすべてのドキュメントの配列が含まれていると予想されます。その配列のサイズは16MBを超えることはできません 、したがって、以下のコードは、非常に小さなドキュメントのコレクションに対してのみ機能します。
コード:
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 } }
])
少し説明が必要なのは、年齢層の計算方法です。
そのために、 $group> 単一の配列に変換してから、 $ addFields 「範囲」-若いグループの最年長の人と年配のグループの最年少の人の間にギャップがある年齢グループの2D配列は2年以上です。
配列は、 $reduce を使用して計算されます。 $ range すべての年齢のインデックスの配列ですが、最初は初期値になります。
削減式は、 $cond です。 現在と以前の差を計算します( $ extract > )すべての年齢の配列の要素。
2より大きい場合は、 $ concatArrays 。それ以外の場合、年齢は$slice<を使用して最も古いグループに追加されます。 / a> 範囲配列の最後のグループにプッシュし、 $ setUnion 重複を排除します。
年齢層が計算されると、 $ lookup > それらを「グループ」配列にグループ化するための年齢別の同じコレクション。