问题
I am using meteor and this is my schema, each is a separate collection:
Courses has many lectures
Lectures have many questions
Questions have many answers
I want 1 page where I can display a given course's lectures, questions, and answers. I can display a course's lectures no problem but I have issues with displaying further nested items. I'd ideally like to have:
Lecture has courseId
Answer has lectureId (but not courseId)
Question has answerId (but not lectureId or courseId)
Is that wise or should I embed courseIds and lectureIds in all child components? This is my iron router, I tried to extend the same idea that worked with nesting lectures with questions but I hit a stumbling block with how to feed the subscriptions the lecturesId:
Router.route('/courses/:_id', {
name: 'CoursePage',
waitOn: function(){
return [
Meteor.subscribe('singleCourse', this.params._id),
Meteor.subscribe('lectures', this.params._id),
Meteor.subscribe('questions', this.params._id)
];
},
data: function() {
return Courses.findOne(this.params._id);
}
});
This is the subscriptions for the course page, again with my stumbling block of not really knowing how to feed in a lectureId:
Template.CoursePage.helpers({
Lectures: function() {
return Lectures.find({courseId: this._id});
},
Questions: function(lectureId) {
return Questions.find({courseId: this._id, lectureId: lectureId});
}
});
Can anyone recommend a good way to do this 4 level nesting for a single page? I think that I am missing something obvious but I can't quite find a good example with google searching.
Thanks!
回答1:
You can Publish Composite package for this. See the following sample code and edit as per your collection schemas,
Meteor.publishComposite('singleCourse', function (courseId) {
return [{
find: function() {
return Courses.find({ id: courseId});
}
}, {
find: function() {
return Lectures.find({ courseId: courseId});
},
children: [{
find: function(lecture) {
return Questions.find({ lectureId: lecture.id });
},
children: [{
find: function(question) {
return Answers.find({ questionId: question.id });
}
}]
}}
}]
});
Then in your router, you can simply make one subscription call,
Router.route('/courses/:_id', {
name: 'CoursePage',
waitOn: function(){
return [
Meteor.subscribe('singleCourse', this.params._id)
];
},
data: function() {
return Courses.findOne(this.params._id);
}
});
This is one of the best packages (if not the best) as of now to reactively publish set of related documents from different collections.
There are some known issues while doing these kind of reactive joins but for smaller datasets, this works without any problem.
Hope it helps.
回答2:
Mongo can support using aggregation. $lookup will let you connect and gather data between your collections like an SQL join.
Using this in meteor requires using an external mongo ($lookup is new as of Mongo 3.2, meteor's Mongo is still 2.6.7) and a package such as the meteorhacks:aggregate package. There are other packages that address this, as mentioned in the comments, aggregate is just what I've used; with it you call Courses.aggregate(...)
per the mongo aggregation documentation to produce the data that you require.
In my use, I had a Meteor method defined that took filter parameters as arguments
'aggregateReport':function(filterPersonnel, filterCourse, filterQuarter){
return Personnel.aggregate([{$match: filterPersonnel}, {$unwind: "$courses"},
{$lookup: {from: "courses", localField: "courses", foreignField: "_id",
as: "course_docs"}}, {$unwind: "$course_docs"}, {$match: filterCourse},
{$match: filterQuarter}]);
The Personnel have: country, course date, lastname, fullname, ..., course #, course. (The ellipses covers non-relevant to the query). The above queries Personnel per the filter, spools it out to one record per course (this is a transcript type of view for many people in a program), then adds the information from Courses as course_docs
to the returned Personnel, and then filters by course parameters and date parameters. code and dependencies were meteor 1.2; Feb 2016
来源:https://stackoverflow.com/questions/35617821/4-level-subscription-nesting-in-meteor