MongoDB
 sql >> база данни >  >> NoSQL >> MongoDB

Използване на съхранени функции на JavaScript в конвейера за агрегиране, MapReduce или runCommand

Всяка функция, която запазите в system.js е наличен за използване от оператори за обработка на "JavaScript", като например $where оператор и mapReduce и може да бъде препратен от _id е присвоена стойност.

db.system.js.save({ 
   "_id": "squareThis", 
   "value": function(a) { return a*a } 
})

И някои данни, вмъкнати в колекцията „извадка“:

{ "_id" : ObjectId("55aafd2bacbed38e06f9eccf"), "a" : 1 }
{ "_id" : ObjectId("55aafea6acbed38e06f9ecd0"), "a" : 2 }
{ "_id" : ObjectId("55aafeabacbed38e06f9ecd1"), "a" : 3 }

След това:

db.sample.mapReduce(
    function() {
       emit(null, squareThis(this.a));
    },
    function(key,values) {
        return Array.sum(values);
    },
    { "out": { "inline": 1 } }
 );

Дава:

   "results" : [
            {
                    "_id" : null,
                    "value" : 14
            }
    ],

Или с $where :

db.sample.find(function() { return squareThis(this.a) == 9 })
{ "_id" : ObjectId("55aafeabacbed38e06f9ecd1"), "a" : 3 }

Но в "нито един" случай можете да използвате глобални като базата данни db справочни или други функции. И двете $where и mapReduce документацията съдържа информация за границите на това, което можете да правите тук. Така че, ако сте мислили, че ще направите нещо като „потърсете данни в друга колекция“, тогава можете да го забравите, защото е „Не е разрешено“.

Всяка Командното действие на MongoDB всъщност е извикване на действие "runCommand" "под капака" така или иначе. Но освен ако това, което тази команда всъщност прави, не е „извикване на машина за обработка на JavaScript“, тогава използването става без значение. Все пак има само няколко команди, които правят това, като mapReduce , group или eval , и разбира се операциите за намиране с $where .

Рамката за агрегиранене използвайте JavaScript по какъвто и да е начин. Може да грешите точно както други са направили изявление като това, което не прави това, което смятате, че прави:

db.sample.aggregate([
    { "$match": {
        "a": { "$in": db.sample.distinct("a") }
    }}
])

Така че това е „не работи вътре " конвейера за агрегиране, а по-скоро "резултата" от този .distinct() повикването се "оценява", преди конвейерът да бъде изпратен към сървъра. Както и с външна променлива се прави така или иначе:

var items = [1,2,3];
db.sample.aggregate([
    { "$match": {
        "a": { "$in": items }
    }}
])

И двете по същество изпращат до сървъра по един и същи начин:

db.sample.aggregate([
    { "$match": {
        "a": { "$in": [1,2,3] }
    }}
])

Така че "не е възможно" да се "извика" която и да е функция на JavaScript в конвейера за агрегиране, нито наистина има смисъл "предаване" на резултатите като цяло от нещо, запазено в system.js . „Кодът“ трябва да бъде „зареден на клиента“ и само JavaScript машина може да направи нещо с него.

С рамката за агрегиране всички налични "оператори" всъщност са естествено кодирани функции, за разлика от интерпретацията на JavaScript в "свободна форма", предоставена за mapReduce . Така че вместо да пишете "JavaScript", вие използвате самите оператори:

db.sample.aggregate([
    { "$group": {
        "_id": null,
        "sqared": { "$sum": {
           "$multiply": [ "$a", "$a" ]
        }}
    }}
])

{ "_id" : null, "sqared" : 14 }

Така че има ограничения за това, което можете да правите с функциите, запазени в system.js, и има вероятност това, което искате да направите, е едно от следните:

  • Не е разрешено, като например достъп до данни от друга колекция
  • Всъщност не се изисква, тъй като логиката обикновено е самостоятелна
  • Или вероятно все пак по-добре имплементиран в клиентска логика или друга различна форма

Почти единствената практическа употреба, за която наистина се сещам, е, че имате редица операции "mapReduce", които не могат да бъдат направени по друг начин и имате различни "споделени" функции, които бихте предпочели просто да съхранявате на сървъра, отколкото да поддържате във всеки Извикване на функция mapReduce.

Но отново, 90-процентната причина за mapReduce над рамката за агрегиране обикновено е, че „структурата на документа“ на колекциите е недобре избрана и JavaScript функционалността е „изисква“ за преминаване през документа за търсене и анализ.

Така че можете да го използвате при разрешените ограничения, но в повечето случаи вероятно изобщо не трябва да го използвате, а да коригирате другите проблеми, които са ви накарали да повярвате, че имате нужда от тази функция на първо място.




  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Как да конфигурирате името на колекцията MongoDb за клас в Spring Data

  2. Автоматично премахване на препращащи обекти при изтриване в MongoDB

  3. MongoDB $arrayElemAt

  4. Използвайте повече от една схема на колекция в mongodb

  5. Вграден документ срещу препратка в модела на дизайн на мангуста?