Search code examples
arraysmongodbmeteorfindmeteor-blaze

Using array to find documents in a collection using Meteor js


Helper method

  GetSchoolId: function () {
            var moduleIdArray=[];
            var myslug = FlowRouter.getParam('myslug');
            var mySchoolId = SchoolDb.findOne({slug: myslug});
            if (mySchoolId) {
                ModuleSchool.find({}, {schoolId: mySchoolId._id}).forEach(function (modulesSelected) {
                    moduleIdArray.push(modulesSelected.moduleId);
                });
                if (typeof moduleIdArray === 'object' && moduleIdArray instanceof Array) {
                    console.log(moduleIdArray);
                    moduleIdArray.forEach(function (moduleIds) {
                        return Modules.find({}, {_id: moduleIds}).fetch();
                    });
                }
            }
        }

Template code:

{{#each GetSchoolId }} 
    <p>{{GetSchoolId.modulename}} </p>
    {{/each}}
    </p>
{{/each}}

I know to Meteor Profs, it is a inch of an iceberg, in seconds it will be trashed. I have 3 collections, one for school record (SchoolDb), second for for module (Modules), and the third, a relationship table (ModuleSchool). modules are assigned to schools.

From the code above, I am able to get the school _id from (SchoolDb) using the slug passed to the route which I used to fetch the schoolId from the relationship table (SchoolDb) and the (ModuleSchool) to return modules assigned to a the school in question. I was able to fetch the module Ids and converted them into arrays, what I now want to do is using the array of Ids fetched from the ModuleSchool to return the module names from the Modules because only the _ids are stored in the relationship table.

The above code does only does it to the level of converting the _ids to array, when I tried printing on the template nothing showed. What wrong am I to right?


Solution

  • To find document with a field corresponding to at least one element of an array you can use $in :

    Template.my_template.helpers({
        modules(){
            var myslug = FlowRouter.getParam('myslug');
            var mySchoolDoc = SchoolDb.findOne({slug: myslug});
            var arrayModuleSchool = ModuleSchool.find({schoolId: mySchoolDoc._id});
            // Transform the array of document into an array with only the ids
            var arrayModuleIds = [];
            arrayModuleSchool.forEach(function(moduleSchool)){
                arrayModuleIds.push(moduleSchool.moduleId);
            });
            return Modules.find({_id: {$in: arrayModuleIds}}).fetch();
        }
    });
    

    And then simply use the {{each}} tag.

    <template name="my_template">
      {{#each module in modules}} 
        <p>{{module.modulename}}</p>
      {{/each}}
    </template>
    

    But if each module is attached to only one school, i suggest a simpler solution for your problem, you don't have to create a collection between school and module.

    You just have to create two collections: Schools and Modules and add to the Modules documents a schoolId field.

    Then your code would look like that :

    Template.my_template.helpers({
        modules(){
            var myslug = FlowRouter.getParam('myslug');
            var mySchoolDoc = Schools.findOne({slug: myslug});
            return Modules.find({schoolId: mySchoolDoc._id}).fetch();
        }
    });