MongoDB
 sql >> Base de Dados >  >> NoSQL >> MongoDB

Mongoose - acessando objeto aninhado com .populate


Aqui está uma versão simplificada do que você deseja.

Dados básicos para configurar, primeiro os "alunos":
{ 
   "_id" : ObjectId("53aa90c83ad07196636e175f"), 
   "name" : "Bill",
   "rollNo" : 1,
   "class" : 12 
},
{ 
    "_id" : ObjectId("53aa90e93ad07196636e1761"),
    "name" : "Ted",
    "rollNo" : 2,
    "class" : 12
}

E então a coleção "equipes":
{ 
    "_id" : ObjectId("53aa91b63ad07196636e1762"),
    "name" : "team1",
    "lead" : "me",
    "students" : [ 
        { 
            "block" : 1,
            "status" : "Y",
            "student" : ObjectId("53aa90c83ad07196636e175f")
        },
        { 
            "block" : 2,
            "status" : "N",
            "student" : ObjectId("53aa90e93ad07196636e1761")
        }
    ]
}

É assim que se faz:
var async = require('async'),
    mongoose = require('mongoose');
    Schema = mongoose.Schema;

mongoose.connect('mongodb://localhost/team');

var teamSchema = new Schema({
  name: String,
  lead: String,
  students: [{
    block: Number,
    status: String,
    student: {
      type: Schema.ObjectId, ref: 'Student'
    }
  }]
});

var studentSchema = new Schema({
  name: String,
  rollNo: Number,
  class: Number
});

var Team = mongoose.model( "Team", teamSchema );
var Student = mongoose.model( "Student", studentSchema );

Team.findById("53aa91b63ad07196636e1762")
  .select('students')
  .exec(function(err, team) {
    console.log( team );

    async.forEach(team.students, function(student,callback) {
      Student.populate(
        student,
        { "path": "student" },
        function(err,output) {
          if (err) throw err;
          callback();
        }
      );
    },function(err) {
      console.log( JSON.stringify( team, undefined, 4 ) );
    });

  });

E dá-lhe os resultados:
{
    "_id": "53aa91b63ad07196636e1762",
    "students": [
        {
            "block": 1,
            "status": "Y",
            "student": {
                "_id": "53aa90c83ad07196636e175f",
                "name": "Bill",
                "rollNo": 1,
                "class": 12
            }
        },
        {
            "block": 2,
            "status": "N",
            "student": {
                "_id": "53aa90e93ad07196636e1761",
                "name": "Ted",
                "rollNo": 2,
                "class": 12
            }
        }
    ]
}

Você realmente não precisa do módulo "assíncrono", mas eu estou apenas "no hábito" por assim dizer. Não "bloqueia" por isso considero melhor.

Então, como você pode ver, você inicializa .populate() chamada não faz nada como espera "chavear" de um _id valor na coleção estrangeira de uma entrada de matriz que "estritamente falando" não é assim, pois a "chave" está em "aluno" contendo a "chave estrangeira".

Eu realmente abordei isso em uma resposta recente aqui , talvez não seja exatamente específico para sua situação. Parece que sua pesquisa não encontrou a "mesma resposta" correta (embora não exatamente) para você extrair referência.