Meteor collections: how to connect to different collections by referencing each other?
I have two collections:
Contracts = new Mongo.Collection('contracts');
Reminders = new Mongo.Collection('reminders');
They are structured in the database like this:
Contracts:
{
"id": "4432234",
"contract": "C-42432432",
"description": "Description of contract",
"counterpart": "Company name",
"status": "awarded"
},
etc.
Memo:
{
"name": "Contract expiring",
"type": "expiring",
"contract": "C-42432432",
"reminderDate": "2015-06-01",
"urgency": 3
},
etc.
Here, the term "contract" refers to "contract" -name in an assembly of contracts. We can use multiple reminders associated with the same contract. So I want them to be in two different collections.
To get the contract details I use:
<template name="example">
{{#each contracts}}
{{description}}
{{/each}}
</template>
matches js:
Template.example.helpers({
contracts: function() {
return Contracts.find();
}
});
This works fine and the result is equal in this case Description of contract
.
But what should I do if I want to display the collection of reminders and get the relevant data from the Contract? In other words: I want to compose a collection of reminders and get the same result.
<template name="notworking">
{{#each reminder}}
{{description}}
<!-- Here I want the description from the Contract-collection -->
{{/each}}
</template>
matches js:
Template.notworking.helpers({
reminder: function() {
//?
}
});
source to share
You might be better off using Contracts._id
to denote a contract from a collection Reminders
in this way, if the name and description of the contract changes at some point, you won't need to update all relevant reminders.
Contract:
{
"_id": "tPN5jopkzLDbGypBu",
"contract": "C-42432432",
"description": "Description of contract",
"counterpart": "Company name",
"status": "awarded"
},
Reminder:
{
"name": "Contract expiring",
"type": "expiring",
"contractId": "tPN5jopkzLDbGypBu",
"reminderDate": "2015-06-01",
"urgency": 3
},
Then, if you want to list reminders and show relevant contract information, you would have:
HTML:
<template name="remindersList>
{{#each reminder}}
Date: {{reminderDate}} Urgency: {{urgency}}
{{#with relatedContract}}
Description: {{description}} Counterpart: {{counterpart}} Status: {{status}}
{{/with}}
{{/each}}
</template>
JS:
Template.remindersList.helpers({
reminder: function(){
return Reminders.find(); // or whatever query you need to run
},
relatedContract: function(){
return Contracts.findOne({_id: this.contractId}); // 'this' will be the Reminder document
}
});
OR - if you wanted to keep your denormalized schema, then the function relatedContract
would simply have to returnContracts.findOne({contract: this.contract})
source to share
I assume you need to iterate over each reminder inside a loop, iterating over each contract:
<template name="contracts">
{{#each contracts}}
<p>{{description}}</p>
{{#each reminders}}
<p>{{description}}</p>
{{/each}}
{{/each}}
</template>
The current data context when evaluating reminders
will be currently under contract, so we can access its contract name with this.contract
.
As a result, you just need to return each dunning document with the same contract name.
Template.contracts.helpers({
reminders: function(){
return Reminders.find({
contract: this.contract
});
}
});
source to share
https://atmospherejs.com/reywood/publish-composite
This package provides a flexible way to publish a set of related documents from different collections using a reactive join. Hope it helps.
source to share