Enhver funktion, du gemmer i system.js
er tilgængelig til brug af "JavaScript"-behandlingsudsagn såsom $where
operator og mapReduce
og kan henvises til med _id
værdi er blev tildelt.
db.system.js.save({
"_id": "squareThis",
"value": function(a) { return a*a }
})
Og nogle data indsat til "sample"-indsamling:
{ "_id" : ObjectId("55aafd2bacbed38e06f9eccf"), "a" : 1 }
{ "_id" : ObjectId("55aafea6acbed38e06f9ecd0"), "a" : 2 }
{ "_id" : ObjectId("55aafeabacbed38e06f9ecd1"), "a" : 3 }
Så:
db.sample.mapReduce(
function() {
emit(null, squareThis(this.a));
},
function(key,values) {
return Array.sum(values);
},
{ "out": { "inline": 1 } }
);
Giver:
"results" : [
{
"_id" : null,
"value" : 14
}
],
Eller med $where
:
db.sample.find(function() { return squareThis(this.a) == 9 })
{ "_id" : ObjectId("55aafeabacbed38e06f9ecd1"), "a" : 3 }
Men i "ingen af" tilfælde kan du bruge globaler såsom databasen db
reference eller andre funktioner. Begge $where
og mapReduce
dokumentationen indeholder oplysninger om grænserne for, hvad du kan gøre her. Så hvis du troede, du ville gøre noget som "slå data op i en anden samling", så kan du glemme det, fordi det er "Ikke tilladt".
Hver MongoDB kommandohandling er faktisk et opkald til en "runCommand"-handling "under motorhjelmen" alligevel. Men medmindre det, den kommando faktisk gør, er at "kalde en JavaScript-behandlingsmotor", så bliver brugen irrelevant. Der er alligevel kun nogle få kommandoer, der gør dette, nemlig mapReduce
, group
eller eval
, og selvfølgelig find-operationerne med $where
.
Det gør aggregeringsrammen ikke bruge JavaScript på nogen måde overhovedet. Du tager måske fejl, ligesom andre har lavet en udtalelse som denne, som ikke gør, hvad du tror, den gør:
db.sample.aggregate([
{ "$match": {
"a": { "$in": db.sample.distinct("a") }
}}
])
Så det er "ikke kører inde " aggregeringspipelinen, men snarere "resultatet" af den .distinct()
opkaldet "evalueres", før pipelinen sendes til serveren. Meget som med en ekstern variabel gøres alligevel:
var items = [1,2,3];
db.sample.aggregate([
{ "$match": {
"a": { "$in": items }
}}
])
Begge sender i det væsentlige til serveren på samme måde:
db.sample.aggregate([
{ "$match": {
"a": { "$in": [1,2,3] }
}}
])
Så det er "ikke muligt" at "kalde" en hvilken som helst JavaScript-funktion i aggregeringspipelinen, og der er heller ikke rigtig nogen mening med at "passere ind" resultater generelt fra noget gemt i system.js
. "Koden" skal "indlæses til klienten", og kun en JavaScript-motor kan faktisk gøre noget med den.
Med aggregeringsrammen er alle tilgængelige "operatører" faktisk indbygget kodede funktioner i modsætning til JavaScript-fortolkningen af "fri form" til rådighed for mapReduce
. Så i stedet for at skrive "JavaScript", bruger du selve operatorerne:
db.sample.aggregate([
{ "$group": {
"_id": null,
"sqared": { "$sum": {
"$multiply": [ "$a", "$a" ]
}}
}}
])
{ "_id" : null, "sqared" : 14 }
Så der er begrænsninger for, hvad du kan gøre med funktioner gemt i system.js, og chancerne er, at det, du vil gøre, er enten:
- Ikke tilladt, f.eks. adgang til data fra en anden samling
- Ikke rigtig påkrævet, da logikken generelt er selvstændig alligevel
- Eller sandsynligvis bedre implementeret i klientlogik eller anden anden form alligevel
Næsten den eneste praktiske brug, jeg virkelig kan komme i tanke om, er, at du har en række "mapReduce"-operationer, som ikke kan gøres på anden måde, og du har forskellige "delte" funktioner, som du hellere vil gemme på serveren end vedligeholde inden for hver mapReduce funktionskald.
Men igen, 90 % årsagen til mapReduce i forhold til aggregeringsrammen er normalt, at samlingernes "dokumentstruktur" er blevet dårligt valgt, og JavaScript-funktionaliteten er "påkrævet" for at gennemse dokumentet til søgning og analyse.
Så du kan bruge det under de tilladte begrænsninger, men i de fleste tilfælde burde du nok slet ikke bruge dette, men løse de andre problemer, der fik dig til at tro, at du havde brug for denne funktion i første omgang.