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

Mohu použít naplnit před agregací v mongoose?

Ne, nemůžete volat .populate() před .aggregate() a existuje velmi dobrý důvod, proč nemůžete. Existují však různé přístupy, které můžete použít.

.populate() metoda funguje „na straně klienta“, kde základní kód ve skutečnosti provádí další dotazy (nebo přesněji $in query ) k "vyhledání" zadaného prvku (prvků) z odkazované kolekce.

Na rozdíl od toho .aggregate() je operace "na straně serveru", takže v podstatě nemůžete manipulovat s obsahem "na straně klienta" a mít tato data k dispozici později pro fáze agregačního kanálu. To vše musí být přítomno ve sbírce, kterou provozujete.

Lepší přístup je k dispozici s MongoDB 3.2 a novějšími prostřednictvím $lookup provoz agregačního potrubí. Také je pravděpodobně nejlepší zpracovat z User kolekce v tomto případě za účelem zúžení výběru:

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

    }
)

To v podstatě zahrnuje nové pole "skóre" v User objekt jako "pole" položek, které se při "vyhledání" shodovaly s jinou sbírkou:

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

Výsledkem je vždy pole, protože obecně očekávané použití je „levé spojení“ možného vztahu „jedna k mnoha“. Pokud žádný výsledek neodpovídá, je to pouze prázdné pole.

Chcete-li použít obsah, stačí pracovat s polem jakýmkoli způsobem. Můžete například použít $arrayElemAt operátora, aby bylo možné získat pouze jeden první prvek pole v budoucích operacích. A pak můžete obsah použít jako jakékoli normální vložené pole:

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

Pokud nemáte k dispozici MongoDB 3.2, pak další možností, jak zpracovat dotaz omezený vztahy jiné kolekce, je nejprve získat výsledky z této kolekce a poté použít $in pro filtrování podle druhého:

// 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) {

        }
    );

});

Jediným způsobem, jak toho dosáhnout v dřívějších verzích, je tedy získání seznamu platných uživatelů z druhé kolekce klientovi a jeho následné odeslání do jiné kolekce v dotazu.




  1. Nainstalujte MongoDB na Mac

  2. mongoengine save metoda je zastaralá?

  3. Jak odečíst dva datum a čas v mongodb

  4. (uzel:63208) Upozornění na zastaralost:collection.ensureIndex je zastaralá. Místo toho použijte createIndexes