集約パイプラインでJavaScript関数を呼び出すことは可能だと思われるかもしれませんが、これはできません。パイプライン内で実行するために、関数の結果から変数の実際の「補間」を間違えています。
たとえば、これを行う場合:
var getNumbers = function() { return [ 1,2,3 ] };
それから私はこれを呼びます:
db.collection.aggregate([
{ "$project": {
"mynums": getNumbers()
}}
])
次に、JavaScriptシェルで実際に何が起こるかは、次のように、命令がサーバーに送信される「補間」および「前」に行われます。
db.collection.aggregate([
{ "$project": {
"mynums": [1,2,3]
}}
])
それをさらに実証するために、関数をサーバーに「のみ」保存します。
db.system.js.save({ "_id": "hello", "value": function() { return "hello" } })
次に、集計ステートメントを実行してみてください:
db.collection.aggregate([
{ "$project": {
"greeting": hello()
}}
])
そして、それは例外になります:
E QUERY [main] ReferenceError:helloは(shell):1:69で定義されていません
これは、実行が「サーバー」ではなく「クライアント」で行われており、関数がクライアントに存在しないためです。
集約フレームワークはできません JavaScriptを実行するためのプロビジョニングがないため、JavaScriptを実行します。すべての操作はネイティブコードで実行され、JavaScriptエンジンは呼び出されません。したがって、代わりに演算子を使用します:
db.collection.aggregate([
{ "$project": {
"total": { "$add": [ 1, 2 ] },
"field_total": { "$subtract": [ "$gross", "$tax" ] }
}}
])
演算子を使用して結果を得ることができない場合、JavaScriptコードを実行できる唯一の方法は、代わりにmapReduceを実行することです。これは、もちろんJavaScriptエンジンを使用してコレクションのデータとインターフェイスします。また、必要に応じて、そこからロジック内のサーバー側関数を参照することもできます。
{ "key": 1, "value": 1 },
{ "key": 1, "value": 2 },
{ "key": 1, "value": 3 }
db.system.js.save({ "_id": "square", "value": function(num) { return num * num } })
db.collection.mapReduce(
function() {
emit(this.key,square(this.value))
},
function(key,values) {
return Array.sum(values);
},
{ "out": { "inline": 1 } }
)
返品:
{
"_id": 1,
"value": 14
}
つまり、これは「フィールド値を渡す方法」ではなく、集約フレームワークがJavaScriptをまったくサポートしておらず、実際に起こっていると思っていたことが実際には当てはまらないという事実に関するものです。