Brian Sizemore Brian Sizemore - 4 months ago 14
Javascript Question

Meteor Mongo $in with an array is only returning the last element

I have two meteor functions that are utilizing mongo collection queries.

UI.registerHelper('studentsInCourse', function() {
var courseID = Router.current().params.courseID;
let userIdArray = Enrollment.find(
{ CourseID: courseID}
).map((e) => { return e.UserID});

console.log(userIdArray); //this array correctly has multiple objs in it


var userArray = Meteor.users.find(
{ _id: { $in: userIdArray }}).map((c) => { return c });

console.log(userArray);
return userArray;

}),

Template.registerHelper('course_list', function(){

let courseIdArray = Enrollment.find(
{ UserID: Meteor.userId(), EducatorFlag: false },
{ fields: { CourseID: 1 }}).map((e) => { return e.CourseID });

return Courses.find(
{ _id: { $in: courseIdArray }}).map((c) => { return c });
})


The course_list function works properly and returns a list of Course objects from the Courses collection. However, the studentsInCourse function properly prints out an array when I log userIdArray yet it only places one user object into userArray. This happens to correspond to the _id of the last object in userIdArray. These functions look identical to me and I do not understand why they are returning differently.

Answer

Taken from the Meteor.users section of the Meteor API Docs:

Like all Mongo.Collections, you can access all documents on the server, but only those specifically published by the server are available on the client.

If you're logged in and are calling the following from the client side

Meteor.users.find({ 
  _id: { 
    $in: userIdArray 
  }
}).map((c) => { return c });

then by default Meteor.users.find() will only return your logged in user details (this is a security feature - you wouldn't want people to be able to get a list of all your users). So your cursor will refer to at most one user. If your logged in user _id is in the userIdArray, then you'll run the associated map function on that user only, which is why you're only getting one user object returned.

If you want to run this against all users on the client side, then you'll want to look into setting up your own subscriptions/publications for sending the user data you want to the client (or look into leveraging Meteor Methods to achieve something similar - you could create a Method to find and return all matching users).