0
votes

I am working on a Meteor project where I have some Mongo Collections and I am not sure how to deal with relationships and the Meteor collection helpers package.

Up until now we have been storing embedded documents, so for instance, we have an Internship collection and every internship has an embedded document with the user (owner) that created this internship.

We have decided to use the Meteor collection helpers package (https://github.com/dburles/meteor-collection-helpers), so we can add methods that returns the values that we need. The problem is the embedded documents lost their given methods.

In the internships we would just store the related collection id, and if we'd like to get the Internship.address that is divided in 3 different properties street, postcode and city we would have just to call 'internship.getAddress()'. Another example would be, getting the internship address if you are dealing with an Application document. You could call the method Application.getInternship().getAddress(). By doing this, we do not have to store an embedded document.

The problem arise when we need to do a Mongo query using different fields. We have a very simple search function that returns all document that matches a given string:

Application.search = (query) => {
    Application.find({
        'applicant._id': Meteor.userId(),
        $or: [
          {"internship.title": { $regex: query, $options: 'i' }},
          {"internship.description": {$regex: query, $options: 'i' }},
        ],
    }, {sort: { updatedAt: -1 },
    }).fetch();
}

Internship.title and descripion are not being stored at the internship embedded document anymore so we wonder how to deal with this.

1

1 Answers

1
votes

Let's say that your Applications collection is related to your Internships collection by an array of internshipIds in the Applications collection. Then you can do the following:

Application.search = (query) => {
  // find cursor internships that match the query
  const matchingInternships = Internships.find({
    $or: [
      {title: { $regex: query, $options: 'i' }},
      {description: {$regex: query, $options: 'i' }}
    ]
  });
  // extract the list of _ids from this cursor
  const intershipIds = matchingInternships.map(i=>{return i._id}); // array of internshipIds
  Application.find({
    'applicant._id': Meteor.userId(),
    internshipId: {$elemMatch: internshipIds } // look for internshipIds that are in the array
    },{sort: { updatedAt: -1 },
  }).fetch();
}

This is somewhat analogous to doing nested SQL SELECT statements, ex:

SELECT * FROM APPLICATIONS WHERE internshipID IN
  (SELECT ID FROM INTERNSHIPS WHERE
    (title LIKE query OR description LIKE query)
  );