Whilst it looks a lot more simple, it's actually introducing more load due to the fact that this issues multiple queries to the database in order to retrieve the data, and not in a single call:Mongoose: groups.find({ survey: { '$in': [ ObjectId("59b6715725dcd2060da7f591") ] } }, { fields: {} })Mongoose: questions.find({ _id: { '$in': [ ObjectId("59b6715725dcd2060da7f594"), ObjectId("59b6715725dcd2060da7f595"), ObjectId("59b6715725dcd2060da7f596"), ObjectId("59b6715725dcd2060da7f597") ] } }, { fields: {} })Mongoose: responses.find({ question: { '$in': [ ObjectId("59b6715725dcd2060da7f594"), ObjectId("59b6715725dcd2060da7f595"), ObjectId("59b6715725dcd2060da7f596"), ObjectId("59b6715725dcd2060da7f597") ] } }, { fields: {} })您可以在修改后的清单中看到模式更改(只是为连接添加了虚拟字段)以及正在执行的代码:You can see the schema changes ( just the addition of virtual fields for the joins ) along with the code in action in the amended listing:const fs = require('fs'), mongoose = require('mongoose'), Schema = mongoose.Schema;mongoose.Promise = global.Promise;mongoose.set('debug',true);const uri = 'mongodb://localhost/nested', options = { useMongoClient: true };const responseSchema = new Schema({ response_text: String, order: String, created_date: Date, question: { type: Schema.Types.ObjectId, ref: 'Question' }});const questionSchema = new Schema({ question_text: String, order: String, created_date: Date, group: { type: Schema.Types.ObjectId, ref: 'Group' }},{ toJSON: { virtuals: true, transform: function(doc,obj) { delete obj.id; return obj; } }});questionSchema.virtual('responses',{ ref: 'Response', localField: '_id', foreignField: 'question'});const groupSchema = new Schema({ name: String, order: String, created_date: Date, survey: { type: Schema.Types.ObjectId, ref: 'Survey' }, questions: [{ type: Schema.Types.ObjectId, ref: 'Question' }]});const surveySchema = new Schema({ company: { type: Schema.Types.ObjectId, ref: 'Company' }, created_date: Date, enabled: Boolean, name: String},{ toJSON: { virtuals: true, transform: function(doc,obj) { delete obj.id; return obj; } }});surveySchema.virtual('groups',{ ref: 'Group', localField: '_id', foreignField: 'survey'});const companySchema = new Schema({});const Company = mongoose.model('Company', companySchema);const Survey = mongoose.model('Survey', surveySchema);const Group = mongoose.model('Group', groupSchema);const Question = mongoose.model('Question', questionSchema);const Response = mongoose.model('Response', responseSchema);function log(data) { console.log(JSON.stringify(data,undefined,2))}(async function() { try { const conn = await mongoose.connect(uri,options); await Promise.all( Object.keys(conn.models).map( m => conn.models[m].remove() ) ); // Initialize data let content = JSON.parse(fs.readFileSync('./jsonSurveys.json')); //log(content); for ( let item of content ) { let survey = await Survey.create(item); let company = await Company.create({ _id: survey.company }); for ( let group of item.groups ) { await Group.create(group); for ( let question of group.questions ) { await Question.create(question); for ( let response of question.responses ) { await Response.create(response); } } } } // Run aggregation let results = await Survey.aggregate([ { "$lookup": { "from": Group.collection.name, "localField": "_id", "foreignField": "survey", "as": "groups" }}, { "$unwind": "$groups" }, { "$lookup": { "from": Question.collection.name, "localField": "groups.questions", "foreignField": "_id", "as": "groups.questions" }}, { "$unwind": "$groups.questions" }, { "$lookup": { "from": Response.collection.name, "localField": "groups.questions._id", "foreignField": "question", "as": "groups.questions.responses" }}, { "$group": { "_id": { "_id": "$_id", "company": "$company", "created_date": "$created_date", "enabled": "$enabled", "name": "$name", "groups": { "_id": "$groups._id", "name": "$groups.name", "order": "$groups.order", "created_date": "$groups.created_date", "survey": "$groups.survey" } }, "questions": { "$push": "$groups.questions" } }}, { "$sort": { "_id": 1 } }, { "$group": { "_id": "$_id._id", "company": { "$first": "$_id.company" }, "created_date": { "$first": "$_id.created_date" }, "enabled": { "$first": "$_id.enabled" }, "name": { "$first": "$_id.name" }, "groups": { "$push": { "_id": "$_id.groups._id", "name": "$_id.groups.name", "order": "$_id.groups.order", "created_date": "$_id.groups.created_date", "survey": "$_id.groups.survey", "questions": "$questions" } } }}, { "$sort": { "_id": 1 } } ]); log(results); let alternate = await Survey.find().populate({ path: 'groups', populate: { path: 'questions', populate: { path: 'responses' } } }); log(alternate); } catch(e) { console.error(e); } finally { mongoose.disconnect(); }})(); 这篇关于来自多个集合的$ lookup和嵌套输出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 09-26 09:12