MongoDB
 sql >> Baza danych >  >> NoSQL >> MongoDB

Korzystanie z przechowywanych funkcji JavaScript w potoku agregacji, MapReduce lub runCommand

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.




  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Jak stronicować z Mongoose w Node.js?

  2. Wyklucz określone pola w indeksie symboli wieloznacznych w MongoDB

  3. Co to jest kursor w MongoDB?

  4. Nie można zablokować dokumentu mongodb. A jeśli muszę?

  5. MongoDB:aktualizuj każdy dokument w jednym polu