Wydaje Ci się, że możliwe jest wywołanie funkcji JavaScript w potoku agregacji, ale nie możesz tego zrobić. Mylisz to, co w rzeczywistości jest „interpolacją” zmiennej z wyniku funkcji do wykonania w potoku.
Na przykład, jeśli to zrobię:
var getNumbers = function() { return [ 1,2,3 ] };
Następnie nazywam to:
db.collection.aggregate([
{ "$project": {
"mynums": getNumbers()
}}
])
Następnie, co faktycznie dzieje się w powłoce JavaScript, wartości są "interpolowane" i "przed" wysłaniem instrukcji na serwer, tak jak to:
db.collection.aggregate([
{ "$project": {
"mynums": [1,2,3]
}}
])
Aby to dodatkowo zademonstrować, zapisz funkcję „tylko” na serwerze:
db.system.js.save({ "_id": "hello", "value": function() { return "hello" } })
Następnie spróbuj uruchomić instrukcję agregacji:
db.collection.aggregate([
{ "$project": {
"greeting": hello()
}}
])
A to spowoduje wyjątek:
E QUERY [główne] ReferenceError:cześć nie jest zdefiniowana w (powłoka)::1:69
Dzieje się tak, ponieważ wykonanie odbywa się na „kliencie”, a nie na „serwerze”, a funkcja nie istnieje na kliencie.
Struktura agregacji nie może uruchom JavaScript, ponieważ nie ma na to żadnego przepisu. Wszystkie operacje wykonywane są w kodzie natywnym, bez wywoływania silnika JavaScript. Dlatego zamiast tego używasz operatorów:
db.collection.aggregate([
{ "$project": {
"total": { "$add": [ 1, 2 ] },
"field_total": { "$subtract": [ "$gross", "$tax" ] }
}}
])
Jeśli nie możesz użyć operatorów do osiągnięcia wyników, jedynym sposobem na uruchomienie kodu JavaScript jest uruchomienie zamiast tego mapReduce, które oczywiście wykorzystuje silnik JavaScript do łączenia się z danymi z kolekcji. Stamtąd możesz również odwołać się do funkcji po stronie serwera w swojej logice, jeśli potrzebujesz:
{ "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 } }
)
Zwroty:
{
"_id": 1,
"value": 14
}
Nie chodzi więc o „jak przekazać wartość pola”, ale tak naprawdę o to, że struktura agregacji w żaden sposób nie obsługuje JavaScript i że to, co myślisz, że się dzieje, tak nie jest.