Изглежда смятате, че е възможно да извикате функция на 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 машина. Затова вместо това използвате операторите там:
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 по никакъв начин и че това, което си мислехте, че се случва, всъщност не е така.