Dowolna funkcja zapisana w system.js
jest dostępny do użycia przez instrukcje przetwarzania „JavaScript”, takie jak $where
operator i mapReduce
i może odwoływać się do _id
przypisano wartość.
db.system.js.save({
"_id": "squareThis",
"value": function(a) { return a*a }
})
I trochę danych wstawionych do kolekcji „próbki”:
{ "_id" : ObjectId("55aafd2bacbed38e06f9eccf"), "a" : 1 }
{ "_id" : ObjectId("55aafea6acbed38e06f9ecd0"), "a" : 2 }
{ "_id" : ObjectId("55aafeabacbed38e06f9ecd1"), "a" : 3 }
Następnie:
db.sample.mapReduce(
function() {
emit(null, squareThis(this.a));
},
function(key,values) {
return Array.sum(values);
},
{ "out": { "inline": 1 } }
);
Daje:
"results" : [
{
"_id" : null,
"value" : 14
}
],
Lub z $where
:
db.sample.find(function() { return squareThis(this.a) == 9 })
{ "_id" : ObjectId("55aafeabacbed38e06f9ecd1"), "a" : 3 }
Ale w przypadku "żadnego" nie możesz użyć globalnych, takich jak baza danych db
odniesienia lub inne funkcje. Oba $where
i mapReduce
dokumentacja zawiera informacje o ograniczeniach tego, co możesz tutaj zrobić. Więc jeśli myślałeś, że zamierzasz zrobić coś w stylu „wyszukać dane w innym zbiorze”, możesz o tym zapomnieć, ponieważ jest to „Niedozwolone”.
Każdy Akcja polecenia MongoDB w rzeczywistości wywołanie akcji „runCommand” „pod maską”. Ale jeśli to polecenie faktycznie nie jest „wywoływaniem silnika przetwarzania JavaScript”, to użycie staje się nieistotne. I tak jest tylko kilka poleceń, które to robią, jak mapReduce
, group
lub eval
i oczywiście operacje wyszukiwania z $where
.
Struktura agregacji nie używać JavaScript w jakikolwiek sposób. Możesz się mylić, tak jak inni zrobili takie oświadczenie, które nie robi tego, co myślisz:
db.sample.aggregate([
{ "$match": {
"a": { "$in": db.sample.distinct("a") }
}}
])
Więc to jest „nie działa wewnątrz potok agregacji, ale raczej „wynik” tego .distinct()
wywołanie jest „oceniane” przed wysłaniem potoku do serwera. Podobnie jak w przypadku zmiennej zewnętrznej, tak czy inaczej:
var items = [1,2,3];
db.sample.aggregate([
{ "$match": {
"a": { "$in": items }
}}
])
Oba wysyłają do serwera w ten sam sposób:
db.sample.aggregate([
{ "$match": {
"a": { "$in": [1,2,3] }
}}
])
Tak więc „nie jest możliwe” „wywołanie” jakiejkolwiek funkcji JavaScript w potoku agregacji, ani też nie ma żadnego punktu, w którym „przekazywanie” wynika ogólnie z czegoś zapisanego w system.js
. „Kod” musi zostać „załadowany do klienta” i tylko silnik JavaScript może z nim coś zrobić.
W ramach agregacji wszystkie dostępne „operatory” są w rzeczywistości natywnie zakodowanymi funkcjami, w przeciwieństwie do „swobodnej” interpretacji JavaScript przewidzianej dla mapReduce
. Więc zamiast pisać „JavaScript”, używasz samych operatorów:
db.sample.aggregate([
{ "$group": {
"_id": null,
"sqared": { "$sum": {
"$multiply": [ "$a", "$a" ]
}}
}}
])
{ "_id" : null, "sqared" : 14 }
Istnieją więc ograniczenia dotyczące tego, co możesz zrobić z funkcjami zapisanymi w system.js, a prawdopodobnie chcesz zrobić:
- Niedozwolone, na przykład dostęp do danych z innej kolekcji
- Nie jest to naprawdę wymagane, ponieważ logika i tak jest generalnie samodzielna
- Lub prawdopodobnie lepiej zaimplementowane w logice klienta lub w innej formie w każdym razie
Prawie jedynym praktycznym zastosowaniem, o którym naprawdę myślę, jest to, że masz wiele operacji „mapReduce”, których nie można wykonać w żaden inny sposób, i masz różne „współdzielone” funkcje, które wolałbyś po prostu przechowywać na serwerze niż utrzymywać w każdym wywołanie funkcji mapReduce.
Ale z drugiej strony 90% powodem, dla którego mapReduce jest nad strukturą agregacji, jest zwykle to, że „struktura dokumentu” kolekcji została źle dobrana, a funkcja JavaScript jest „wymagana” do przeszukiwania dokumentu w celu wyszukiwania i analizy.
Możesz więc z niej korzystać w ramach dozwolonych ograniczeń, ale w większości przypadków prawdopodobnie nie powinieneś jej w ogóle używać, ale naprawiaj inne problemy, które sprawiły, że sądzisz, że potrzebujesz tej funkcji w pierwszej kolejności.