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

Kan jeg bruge populate before aggregate i mongoose?

Nej, du kan ikke kalde .populate() før .aggregate() , og der er en meget god grund til, at du ikke kan. Men der er forskellige tilgange, du kan tage.

.populate() metoden fungerer på "klientsiden", hvor den underliggende kode faktisk udfører yderligere forespørgsler (eller mere præcist en $in query ) for at "slå op" det eller de specificerede element(er) fra den refererede samling.

I modsætning hertil .aggregate() er en "serverside"-operation, så du kan dybest set ikke manipulere indholdet "klientside", og så have disse data tilgængelige for aggregeringspipeline-stadierne senere. Det hele skal være til stede i den samling, du opererer på.

En bedre tilgang her er tilgængelig med MongoDB 3.2 og nyere via $lookup drift af aggregeringsrørledning. Også nok bedst at håndtere fra Bruger samling i dette tilfælde for at indsnævre udvalget:

User.aggregate(
    [
        // Filter first
        { "$match": {
            "age": { "$gt": 20 } 
        }},
        // Then join
        { "$lookup": {
            "from": "scores",
            "localField": "userID",
            "foriegnField": "userID",
            "as": "score"
        }},
        // More stages
    ],
    function(err,results) {

    }
)

Dette vil grundlæggende inkludere et nyt felt "score" i Bruger objekt som en "array" af elementer, der matchede på "opslag" til den anden samling:

{
    "userID": "abc",
    "age": 21,
    "score": [{
        "userID": "abc",
        "score": 42,
        // other fields
    }]
}

Resultatet er altid et array, da den generelle forventede brug er en "venstresammenføjning" af et muligt "en til mange"-forhold. Hvis intet resultat matches, er det bare et tomt array.

For at bruge indholdet skal du bare arbejde med et array på nogen måde. For eksempel kan du bruge $arrayElemAt operatør for blot at få det enkelte første element i arrayet i eventuelle fremtidige operationer. Og så kan du bare bruge indholdet som et hvilket som helst normalt indlejret felt:

        { "$project": {
            "userID": 1,
            "age": 1,
            "score": { "$arrayElemAt": [ "$score", 0 ] }
        }}

Hvis du ikke har MongoDB 3.2 tilgængelig, så er din anden mulighed for at behandle en forespørgsel begrænset af relationerne til en anden samling først at hente resultaterne fra den samling og derefter bruge $in for at filtrere på den anden:

// Match the user collection
User.find({ "age": { "$gt": 20 } },function(err,users) {

    // Get id list      
    userList = users.map(function(user) {
       return user.userID;
    });

    Score.aggregate(
        [ 
            // use the id list to select items
            { "$match": {
                "userId": { "$in": userList }
            }},
            // more stages
        ],
        function(err,results) {

        }
    );

});

Så ved at få listen over gyldige brugere fra den anden samling til klienten og derefter føre den til den anden samling i en forespørgsel er den eneste måde at få dette til at ske i tidligere udgivelser.




  1. multipel dokumenttransaktion virker ikke i c# ved hjælp af mongodb 4.08 community server

  2. Forskelle mellem Microsoft.Extensions.Cashing.Redis og Microsoft.Extensions.Caching.StackExchangeRedis.RedisCache

  3. ude af stand til at bruge regex i $in operator i mongodb

  4. MongoDB dokumentdesign til kommentarer (og deres svarkommentarer)