MongoDB
 sql >> база данни >  >> NoSQL >> MongoDB

Мога ли да използвам populate преди aggregate в mongoose?

Не, не можете да извикате .populate() преди .aggregate() и има много добра причина да не можете. Но има различни подходи, които можете да предприемете.

.populate() методът работи от страна на клиента, където основният код всъщност изпълнява допълнителни заявки (или по-точно $in query ), за да „потърсите“ посочения(те) елемент(и) от референтната колекция.

За разлика от .aggregate() е операция от страна на сървъра, така че по същество не можете да манипулирате съдържание от страна на клиента и след това да разполагате с тези данни за етапите на тръбопровода за агрегиране по-късно. Всичко това трябва да присъства в колекцията, с която работите.

По-добър подход тук е наличен с MongoDB 3.2 и по-нови версии, чрез $lookup работа на тръбопровод за агрегиране. Вероятно е най-добре да се работи от User колекция в този случай, за да стесните избора:

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

    }
)

Това основно ще включва ново поле "резултат" в User обект като "масив" от елементи, които съответстват при "търсене" на другата колекция:

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

Резултатът винаги е масив, тъй като общото очаквано използване е "ляво съединение" на възможна връзка "едно към много". Ако няма съответстващ резултат, това е просто празен масив.

За да използвате съдържанието, просто работете с масив по какъвто и да е начин. Например можете да използвате $arrayElemAt оператор, за да получите само първия елемент от масива при всякакви бъдещи операции. И тогава можете просто да използвате съдържанието като всяко нормално вградено поле:

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

Ако не разполагате с MongoDB 3.2, тогава другата ви опция за обработка на заявка, ограничена от отношенията на друга колекция, е първо да получите резултатите от тази колекция и след това да използвате $in за филтриране на втория:

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

        }
    );

});

Така че получаването на списъка с валидни потребители от другата колекция на клиента и след това подаването му на другата колекция в заявка е единственият начин това да се случи в по-ранни версии.




  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Какъв е правилният начин за работа с ISODate в Mongoose

  2. Как да намеря топ 5 стойности в mongodb? и не трябва да съдържа същата стойност

  3. Как да тествам метод, който се свързва с mongo, без всъщност да се свързва с mongo?

  4. Mongoexport -q ISODate заявка

  5. mongoDB заявка за извличане от колекция от вложени масиви