sql >> Databasteknik >  >> NoSQL >> MongoDB

Gruppera dokument i par med mongo-aggregation

Detta är något som helt enkelt inte kan göras med aggregeringsramverket, och den enda nuvarande MongoDB-metoden som är tillgänglig för denna typ av operation är mapReduce.

Anledningen är att aggregeringsramverket inte har något sätt att hänvisa till något annat dokument i pipelinen än det nuvarande. Detta gäller faktiskt också för "gruppering" av pipelinestadier, eftersom även om saker är grupperade på en "nyckel" kan du inte riktigt hantera enskilda dokument på det sätt du vill.

MapReduce å andra sidan har en funktion tillgänglig som låter dig göra vad du vill här, och den är inte ens "direkt" relaterad till aggregering. Det är i själva verket förmågan att ha "globalt scoped variabler" över alla stadier. Och att ha en "variabel" för att i princip "lagra det sista dokumentet" är allt du behöver för att uppnå ditt resultat.

Så det är ganska enkel kod, och det krävs faktiskt ingen "reduktion":

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

Vilket ger dig ett resultat ungefär så här:

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

Det är egentligen bara att välja "något unikt" som det utsända _id värde snarare än något specifikt, eftersom allt detta egentligen gör är skillnaden mellan värden på olika dokument.

Globala variabler är vanligtvis lösningen på dessa typer av "parning"-aggregationer eller producerar "löpande totaler". Just nu har aggregeringsramverket ingen tillgång till globala variabler, även om det kan vara bra att ha. MapReduce-ramverket har dem, så det är förmodligen rimligt att säga att de också borde vara tillgängliga för aggregeringsramverket.

Just nu är de dock inte det, så håll dig till mapReduce.




  1. Det går inte att ansluta till mongo docker-bild med mongoose

  2. Hur implementerar man twitter och facebook api som markörbaserad paginering i mongodb i nodejs med den officiella mongodb-klienten?

  3. Hur man använder aggregeringsfunktionen mongo db-query

  4. Uppdaterar ett rekord med mongoose