Search code examples
htmlmongodbmeteormeteor-blaze

Meteor/Mongo - How to write a query to get data from a separate data context


I've got two separate collections, Patients and Invoices:

Patients Collection

{
  first_name: ...
  surname: ...
  ...
}


Invoices Collection:

{
  invoice_no: ...
  patient_id: ...
  ...
}

I want to display a table that shows all the invoices. Amongst the columns, I'd like to show the patient that the invoice is related to (I've got the patient_id as one of the fields in the Invoices collection).

So I have this helper:

Template.showInvoices.helpers({
  invoices: function () {
    return Invoices.find(); // i know this isn't ideal.
  }
});

And this is the template:

<template name="showInvoices">
  {{#each invoices}}
    <tr>
      <td>{{invoice_no}}</td>
      <td> [PATIENT NAME] </td>
    </tr>
  {{/each}}
</template>

How can I get the patient name from within the invoices data context? Coming from MySQL and relational databases, I can't help but wonder if this is the right design for my particular case because I'm not entirely sure how to perform this query. Should I just change my design?


Solution

  • You can take advantage of the optional transformation function transform that is available when you are defining a collection. The transform option is a function that takes document as a parameter and can be modified. Documents will be passed through this function before being returned from fetch or findOne, and before being passed to callbacks of observe, map, forEach, allow, and deny hence this will allow you to embed data from another collecion synonymous to a join.

    For example, if you are to refactor your meteor app, you can redefine your Invoices collection as follows:

    Invoices = new Mongo.Collection('invoices', {
        transform: function(doc) {
            doc.patient = Patients.findOne(doc.patient_id);
            return doc;
        }
    });
    

    Now when you call Invoices.find().fetch() in your helper, you will have access to the patient property which is a Patient document:

    Template.showInvoices.helpers({
        invoices: function () {
            return Invoices.find().fetch(); 
        }
    });
    

    Template:

    <template name="showInvoices">
        {{#each invoices}}
            <tr>
                <td>{{invoice_no}}</td>
                <td>{{patient.first_name}}</td>
            </tr>
        {{/each}}
    </template>