次のデータを含むコレクションがあります。
{
"_id" : ObjectId("5516d416d0c2323619ddbca8"),
"date" : "28/02/2015",
"driver" : "user1",
"passengers" : [
{
"user" : "user2",
"times" : 2
},
{
"user" : "user3",
"times" : 3
}
]
}
{
"_id" : ObjectId("5516d517d0c2323619ddbca9"),
"date" : "27/02/2015",
"driver" : "user2",
"passengers" : [
{
"user" : "user1",
"times" : 2
},
{
"user" : "user3",
"times" : 2
}
]
}
そして、特定の乗客について、特定のドライバーと一緒にいた時間を知るために、集計を実行したいと思います。私の例では、次のようになります。foruser1:[{ driver: user2, times: 2}]
user2の場合:[{ driver: user1, times: 2}]
user3の場合:[{ driver: user1, times: 3}, {driver: user2, times:2}]
私はmongoにまったく慣れておらず、sumを使用して簡単な集計を実行する方法を知っていますが、配列内にある場合や、サブジェクト自体が配列内にある場合はそうではありません。この種の集計を実行する適切な方法は何ですか?より具体的には、express.jsベースのサーバーでどのように実行しますか?
集約フレームワークでニーズを達成するために、最初のパイプラインステージは、ドキュメントを乗客のユーザーと照合する、問題の乗客に対する $match
操作です。配列の後に $unwind
操作が続きます。この操作は、前の操作の入力ドキュメントから乗客配列を分解して、各要素のドキュメントを出力します。分解された配列に対する別の$match
操作が続き、前のドキュメントストリームをさらにフィルタリングして、一致するドキュメントのみが変更されずに次のパイプラインステージに渡されるようにします。これにより、必要なフィールドが-で投影されます。 $project
演算子。したがって、基本的にuser3
の集約パイプラインは次のようになります。
db.collection.aggregate([
{
"$match": {
"passengers.user": "user3"
}
},
{
"$unwind": "$passengers"
},
{
"$match": {
"passengers.user": "user3"
}
},
{
"$project": {
"_id": 0,
"driver": "$driver",
"times": "$passengers.times"
}
}
])
結果:
/* 0 */
{
"result" : [
{
"driver" : "user1",
"times" : 3
},
{
"driver" : "user2",
"times" : 2
}
],
"ok" : 1
}
[〜#〜]更新[〜#〜]:
日付の異なるドライバーで重複をグループ化する場合は、前述のように、最後の直前に $group
操作を実行できます$project
$sum
演算子を使用して総乗客時間を計算するパイプラインステージ:
db.collection.aggregate([
{
"$match": {
"passengers.user": "user3"
}
},
{
"$unwind": "$passengers"
},
{
"$match": {
"passengers.user": "user3"
}
},
{
"$group": {
"_id": "$driver",
"total": {
"$sum": "$passengers.times"
}
}
},
{
"$project": {
"_id": 0,
"driver": "$_id",
"total": 1
}
}
])
結果:
/* 0 */
{
"result" : [
{
"total" : 2,
"driver" : "user2"
},
{
"total" : 3,
"driver" : "user1"
}
],
"ok" : 1
}