MongoDB
 sql >> Baza danych >  >> NoSQL >> MongoDB

Czy mogę użyć opcji Wypełnij przed agregacją w manguście?

Nie, nie możesz wywołać .populate() przed .aggregate() i jest bardzo dobry powód, dla którego nie możesz. Ale można zastosować różne podejścia.

.populate() metoda działa "po stronie klienta", gdzie bazowy kod faktycznie wykonuje dodatkowe zapytania (a dokładniej $in query ), aby „wyszukać” określone elementy z kolekcji, do której się odwołuje.

Natomiast .aggregate() jest operacją „po stronie serwera”, więc w zasadzie nie można manipulować treścią „po stronie klienta”, a następnie udostępnić te dane etapom potoku agregacji. Wszystko musi być obecne w kolekcji, na której operujesz.

Lepsze podejście jest dostępne w MongoDB 3.2 i nowszych, za pośrednictwem $lookup działanie potoku agregacji. Również prawdopodobnie najlepiej obsługiwać z User w tym przypadku w celu zawężenia wyboru:

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

    }
)

Zasadniczo będzie to zawierać nowe pole "score" w User obiekt jako „tablica” elementów, które zostały dopasowane podczas „wyszukiwania” do innej kolekcji:

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

Wynikiem jest zawsze tablica, ponieważ ogólne oczekiwane użycie to „lewe sprzężenie” możliwej relacji „jeden do wielu”. Jeśli żaden wynik nie zostanie dopasowany, jest to po prostu pusta tablica.

Aby wykorzystać zawartość, po prostu pracuj z tablicą w dowolny sposób. Na przykład możesz użyć $arrayElemAt operatora, aby w przyszłych operacjach uzyskać tylko pierwszy element tablicy. A potem możesz po prostu użyć treści jak każdego normalnego osadzonego pola:

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

Jeśli nie masz dostępnego MongoDB 3.2, inną opcją przetwarzania zapytania ograniczonego relacjami z innej kolekcji jest najpierw pobranie wyników z tej kolekcji, a następnie użycie $in filtrować po drugim:

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

        }
    );

});

Zatem pobranie listy poprawnych użytkowników z innej kolekcji do klienta, a następnie przekazanie jej do innej kolekcji w zapytaniu jest jedynym sposobem, aby to się stało we wcześniejszych wydaniach.




  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Konwertuj .NET Guid na MongoDB ObjectID

  2. Java Future — uwierzytelnianie Spring jest puste w AuditorAware

  3. Jak utworzyć pole automatycznego przyrostu

  4. Jak mogę przeprowadzić wyszukiwanie warunkowe w pymongo?

  5. Elem match zwraca wszystkie dane, podczas gdy ja potrzebuję tylko wybranych danych