🧩
【MongoDB】groupを用いた集計で中央値を取得したい
概要
MongoDBではMongoDBの集計($group, $match, $sum, $avgなど)の記事にある通り、キーを指定して合計や平均などを集計することができます。
MongoDB 7.0からmedian (aggregation)という中央値を取得できる機能が追加されたようなので、今回試してみました。
前提
- 使用したMongoDBのバージョンは
7.0
です。
実装サンプル
今回はRustでクエリを実装してみました。memo_list
という配列項目の配下のevaluation
の値を集計します。
MongoDB group by array inner-elementsの記事を参考に、一度配列をunwindした後に集計しています。
pub async fn get_sample_post_evaluation_aggregate(
db: Database,
account_user_id: String,
) -> Result<Vec<db_model::SamplePostAggregate>, Error> {
let collection = db.collection::<db_model::SamplePost>(db_model::SAMPLE_POST_COLLECTION);
// 集計して中央値を取得するクエリ
let mut pipeline = vec![
doc! { "$match": doc! { "account_user_id": account_user_id.clone() } },
doc! { "$unwind": "$memo_list" },
doc! { "$group": doc! {
"_id": doc! { "name": "$memo_list.name" },
"median": doc! { "$median": doc! { "input":"$memo_list.evaluation", "method": "approximate" } },
} },
];
// 取得した結果を集計用のmodelにparse
let mut results: Vec<db_model::SamplePostAggregate> = Vec::new();
let aggregate_result = collection.aggregate(pipeline, None).await;
match aggregate_result {
Ok(cur) => {
let mut cur_mut = cur;
while let Some(result) = cur_mut.try_next().await? {
if let Ok(post_aggregate) =
bson::from_document::<db_model::SamplePostAggregate>(result)
{
results.push(post_aggregate)
}
}
}
Err(error) => return Err(error),
}
return Ok(results);
}
Discussion