mapReduceに頼らずに、集約フレームワークの下でこれにアプローチする方法はいくつかあります。最近のMongoDB2.6以降のバージョンには、を使用してここで役立つ演算子がいくつかあります。 $let
および$map
変数を定義し、配列を処理するため。
外部宣言は、次のような目的に適しています:
var norm = [
{ "key": 1, "value": 1 },
{ "key": 2, "value": 1.16 },
{ "key": 3, "value": 1.413 },
{ "key": 4, "value": 1.622 },
{ "key": 5, "value": 1.6 },
{ "key": 6, "value": 1.753 },
{ "key": 7, "value": 3.001 },
{ "key": 8, "value": 2.818 },
{ "key": 9, "value": 3.291 },
{ "key": 10,"value": 2.824 },
{ "key": 11, "value": 2.993 },
{ "key": 12, "value": 2.699 },
{ "key": 13, "value": 1.099 },
{ "key": 14, "value": 1.035 },
{ "key": 15, "value": 1.172 },
{ "key": 16, "value": 1.013 },
{ "key": 17, "value": 0.9936 },
{ "key": 18, "value": 1.069 }
];
次に、集計ステートメントを処理します。
db.mycoll.aggregate([
{ "$match": {
"_id.day" : ISODate("2014-06-19T00:00:00.000Z"),
"_id.lt" : "l",
"_id.rt" : "rltdlsts",
"_id.m": false
}},
{ "$unwind": "$value.rl" },
{ "$match": { "value.rl.p": { "$gte": 1, "$lte": 18 } } },
{ "$project": {
"value": 1,
"norm": {
"$let": {
"vars": {
"norm": norm
},
"in": {
"$setDifference": [
{ "$map": {
"input": "$$norm",
"as": "norm",
"in": {
"$cond": [
{ "$eq": [ "$$norm.key", "$value.rl.p" ] },
"$$norm.value",
false
]
}
}},
[false]
]
}
}
}
}},
{ "$unwind": "$norm" }
{ "$group": {
"_id": "$value.rl.a",
"v": { "$sum": "$value.rl.v" },
"c": { "$sum": "$value.rl.c" },
"nv": { "$sum": { "$multiply": [ "$norm", "$value.rl.v" ] } }
}}
])
その中で$project
ステージでは、実際に外部宣言を配列変数としてパイプラインに挿入し、既存の「value.rl.p」キーと一致するように各要素を処理します。これは単一の一致する値のみを返すため、 $unwind
実際には、単一の要素配列の結果を、後の $group
声明。
演算子がサポートされていない以前のバージョンの従来のアプローチは、ネストされた $cond
各値を評価するステートメント:
db.mycoll.aggregate([
{ "$match": {
"_id.day" : ISODate("2014-06-19T00:00:00.000Z"),
"_id.lt" : "l",
"_id.rt" : "rltdlsts",
"_id.m": false
}},
{ "$unwind": "$value.rl" },
{ "$match": { "value.rl.p": { "$gte": 1, "$lte": 18 } } },
{ "$group": {
"_id": "$value.rl.a",
"v": { "$sum": "$value.rl.v" },
"c": { "$sum": "$value.rl.c" },
"nv": { "$sum": { "$multiply": [
{ "$cond": [
{ "$eq": [ "$value.rl.p", 2 },
1.16
{ "$cond": [
{ "$eq": [ "$value.rl.p", 3 },
1.413,
{ "$cond": [
{ "$eq": [ "$value.rl.p", 4 },
1.622,
{ "$cond": [
{ "$eq": [ "$value.rl.p", 5 },
1.6,
{ "$cond": [
{ "$eq": [ "$value.rl.p", 6 },
1.753,
{ "$cond": [
{ "$eq": [ "$value.rl.p", 7 },
3.001,
{ "$cond": [
{ "$eq": [ "$value.rl.p", 8 },
2.818,
{ "$cond": [
{ "$eq": [ "$value.rl.p", 9 },
3.291,
{ "$cond": [
{ "$eq": [ "$value.rl.p", 10 },
2.824,
{ "$cond": [
{ "$eq": [ "$value.rl.p", 11 },
2.993,
{ "$cond": [
{ "$eq": [ "$value.rl.p", 12 },
2.699,
{ "$cond": [
{ "$eq": [ "$value.rl.p", 13 },
1.099,
{ "$cond": [
{ "$eq": [ "$value.rl.p", 14 },
1.035,
{ "$cond": [
{ "$eq": [ "$value.rl.p", 15 },
1.172,
{ "$cond": [
{ "$eq": [ "$value.rl.p", 16 },
1.013,
{ "$cond": [
{ "$eq": [ "$value.rl.p", 17 },
0.9936,
{ "$cond": [
{ "$eq": [ "$value.rl.p", 18 },
1.069,
1
]}
]}
]}
]}
]}
]}
]}
]}
]}
]}
]}
]}
]}
]}
]}
]}
]},
"$value.rl.v"
]}}
}}
])
ノイズが多いように見えますが、前に示したクエリの次に効率的な形式です。実際には、パイプラインステージを生成するのは、ここに表示 と同様の方法です。 。