MongoDB
 sql >> Database >  >> NoSQL >> MongoDB

Raggruppamento di documenti a coppie utilizzando l'aggregazione mongo

Questo è qualcosa che semplicemente non può essere fatto con il framework di aggregazione e l'unico metodo MongoDB attualmente disponibile per questo tipo di operazione è mapReduce.

Il motivo è che il quadro di aggregazione non ha modo di fare riferimento a nessun altro documento in cantiere rispetto a quello attuale. Questo vale anche per le fasi di "raggruppamento" della pipeline, poiché anche se le cose sono raggruppate su una "chiave" non puoi davvero gestire i singoli documenti nel modo desiderato.

MapReduce d'altra parte ha una funzionalità disponibile che ti consente di fare ciò che vuoi qui e non è nemmeno "direttamente" correlata all'aggregazione. In effetti, è la capacità di avere "variabili con ambito globale" in tutte le fasi. E avere una "variabile" per "memorizzare l'ultimo documento" è tutto ciò che ti serve per ottenere il tuo risultato.

Quindi è un codice abbastanza semplice e in effetti non è richiesta alcuna "riduzione":

db.collection.mapReduce(
    function () {
      if (lastVal != null)
        emit( this._id, this.val - lastVal );
      lastVal = this.val;
    },
    function() {}, // mapper is not called
    {
        "scope": { "lastVal": null },
        "out": { "inline": 1 }
    }
)

Il che ti dà un risultato molto simile a questo:

{
    "results" : [
            {
                    "_id" : ObjectId("54a425a99b8bcd6f73e2d662"),
                    "value" : 2
            },
            {
                    "_id" : ObjectId("54a425a99b8bcd6f73e2d663"),
                    "value" : 3
            },
            {
                    "_id" : ObjectId("54a425a99b8bcd6f73e2d664"),
                    "value" : 4
            }
    ],
    "timeMillis" : 3,
    "counts" : {
            "input" : 4,
            "emit" : 3,
            "reduce" : 0,
            "output" : 3
    },
    "ok" : 1
}

In realtà è solo selezionare "qualcosa di unico" come _id emesso valore piuttosto che qualcosa di specifico, perché tutto ciò che sta facendo è davvero la differenza tra valori su documenti diversi.

Le variabili globali sono solitamente la soluzione a questi tipi di aggregazioni di "abbinamento" o di produzione di "totali correnti". In questo momento il framework di aggregazione non ha accesso alle variabili globali, anche se potrebbe essere bello averlo. Il framework mapReduce li ha, quindi è probabilmente corretto dire che dovrebbero essere disponibili anche per il framework di aggregazione.

Al momento non lo sono, quindi resta con mapReduce.