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?
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>