sql >> Databáze >  >> NoSQL >> MongoDB

Vlastní funkce vypočítané sloupce mongodb projekce

Zdá se, že si myslíte, že je možné volat funkci JavaScriptu v agregačním kanálu, ale nemůžete to udělat. Mýlíte se, co je vlastně "interpolace" proměnné z výsledku funkce pro provádění v rámci kanálu.

Například když udělám toto:

var getNumbers = function() { return [ 1,2,3 ] };

Pak tomu říkám:

db.collection.aggregate([
    { "$project": {
        "mynums": getNumbers()
    }}  
])

Poté, co se ve skutečnosti stane v prostředí JavaScriptu, hodnoty jsou „interpolovány“ a „před“ je instrukce odeslána na server, takto:

db.collection.aggregate([
    { "$project": {
        "mynums": [1,2,3]
    }}  
])

Chcete-li to dále demonstrovat, uložte funkci „pouze“ na server:

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

Potom zkuste spustit příkaz agregace:

db.collection.aggregate([
    { "$project": {
        "greeting": hello()
    }}  
])

A to bude mít za následek výjimku:

E QUERY [main] ReferenceError:hello není definováno v (shell):1:69

Je to proto, že spouštění probíhá na "klientovi" a ne na "serveru" a funkce na klientovi neexistuje.

Agregační rámec nemůže spusťte JavaScript, protože k tomu nemá žádné ustanovení. Všechny operace jsou prováděny v nativním kódu, aniž by byl vyvolán žádný JavaScript engine. Proto tam místo toho použijete operátory:

db.collection.aggregate([
    { "$project": {
        "total": { "$add": [ 1, 2 ] },
        "field_total": { "$subtract": [ "$gross", "$tax" ] }
    }}  
])   

Pokud nemůžete použít operátory k dosažení výsledků, pak jediným způsobem, jak můžete spustit kód JavaScript, je místo toho spustit mapReduce, který samozřejmě používá JavaScript engine pro propojení s daty z kolekce. A odtud můžete také odkazovat na funkci na straně serveru uvnitř vaší logiky, pokud potřebujete:

{ "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 } }
)

Vrátí:

{
    "_id": 1,
    "value": 14
}

Nejde tedy o to „jak předat hodnotu pole“, ale ve skutečnosti o skutečnost, že agregační rámec žádným způsobem nepodporuje JavaScript a že to, co jste si mysleli, že se děje, ve skutečnosti není.




  1. Jak nakonfigurovat redis-cluster při použití spring-data-redis 1.7.0.M1

  2. Fungování dekorátoru @cache_page() v django-redis-cache

  3. MongoDB Porovnat pole s $type?

  4. Vícejazyčné datové modelování na MongoDB