2015-05-07 3 views
2

Представьте, у вас есть следующие мангуста схемы:Фильтр суб документов по суб-суб документа

mongoose.model('Team', mongoose.Schema(
{ 
players : [{ 
    trikots : [{ 
     isNew : Boolean, 
     color : String 
    }] 
}] 
}) 

Я хочу запросить свои данные, чтобы получить все команды, которые соответствуют следующим

  • имеют trikots {isNew: правда, цвет: красный}
  • только выбрать игроков, которые имеют trikots {isNew: правда, цвет: красный}

Я начал с использования $ elemMatch для суб-поддокумента, но их все еще ложных игроков. Нужно ли использовать aggregate()? И как?

ответ

1

Да, это вполне достижимо с aggregation framework. Ваш агрегатный конвейер будет состоять из оператора $match, который станет начальным этапом. Это фильтрует документы в коллекции по указанным критериям. Следующими этапами перехода будут пара операторов $uniwnd на обоих массивах, players и вложенных . После $uniwnd вам понадобится еще $match, чтобы затем фильтровать документы с деконструированным массивом до требуемых критериев, которые станут вашим окончательным решением.

Давайте продемонстрируем это, вставив пару документов с помощью данной схемы в коллекции команды в Монго оболочки:

db.team.insert([ 
{ 
    "players" : [ 
     { 
      "trikots" : [ 
       { 
        "isNew" : true, 
        "color" : "red" 
       }, 
       { 
        "isNew" : true, 
        "color" : "blue" 
       } 
      ] 
     }, 
     { 
      "trikots" : [ 
       { 
        "isNew" : false, 
        "color" : "red" 
       }, 
       { 
        "isNew" : true, 
        "color" : "green" 
       } 
      ] 
     } 
    ] 
}, 
{ 
    "players" : [ 
     { 
      "trikots" : [ 
       { 
        "isNew" : false, 
        "color" : "red" 
       }, 
       { 
        "isNew" : false, 
        "color" : "blue" 
       } 
      ] 
     } 
    ] 
} 
]) 

выше трубопровода агрегация может быть реализован следующим образом:

var pipeline = [ 
    { 
     "$match": { 
      "players.trikots.isNew": true, 
      "players.trikots.color": "red" 
     } 
    }, 
    { 
     "$unwind": "$players" 
    }, 
    { 
     "$unwind": "$players.trikots" 
    }, 
    { 
     "$match": { 
      "players.trikots.isNew": true, 
      "players.trikots.color": "red" 
     } 
    } 
]; 
db.team.aggregate(pipeline); 

Выход:

/* 1 */ 
{ 
    "result" : [ 
     { 
      "_id" : ObjectId("554bce9a2ba32ccf7f139bae"), 
      "players" : { 
       "trikots" : { 
        "isNew" : true, 
        "color" : "red" 
       } 
      } 
     } 
    ], 
    "ok" : 1 
} 

Ваш агрегация мангуст был бы похож:

Team.aggregate(pipeline).exec(callback); 

или с помощью Мангуст aggregation pipeline builder для беглого разговора:

Team.aggregate() 
    .match({"players.trikots.isNew": true,"players.trikots.color": "red"}) 
    .unwind("players") 
    .unwind("players.trikots") 
    .match({"players.trikots.isNew": true,"players.trikots.color": "red"}) 
    .exec(callback); 
+0

Теперь я получаю следующую ошибку: «исключение: имена FieldPath поля не может начинаться с ' $».» Какие-либо предложения? –

+0

@FlorianMozart Мои извинения Я дал вам непроверенный код, я обновил ответ, поэтому дайте ему попробовать и дайте мне знать. – chridam

+0

Последний вопрос: если у меня есть несколько игроков из одной команды, у которых есть требования. Как я могу агрегировать, чтобы получить один командный объект со всеми этими игроками? –

Смежные вопросы