Meteor collections: how to connect to different collections referring to each other?

218 views Asked by At

I have two collections:

Contracts = new Mongo.Collection('contracts');
Reminders = new Mongo.Collection('reminders');

These are structured in the database more or less like this:

Contracts:

{
  "id": "4432234",
  "contract": "C-42432432",
  "description": "Description of contract",
  "counterpart": "Company name",
  "status": "awarded"
},
etc.

Reminders:

{
  "name": "Contract expiring",
  "type": "expiring",
  "contract": "C-42432432",
  "reminderDate": "2015-06-01",
  "urgency": 3
},
etc.

The "contract"-name here are referring to a "contract"-name in the contract-collection. We can ha multiple reminders connected to the same contract. Therefore I want them in two different collections.

To get the contract-data I use:

<template name="example">
{{#each contracts}}
    {{description}}
{{/each}}
</template>

corresponding js:

Template.example.helpers({
  contracts: function() {
    return Contracts.find();
  }
});

This works ok and the result in this instance is Description of contract.

But what do I do if I want to display the reminder-collection and get the corresponding data from the Contract-collection? In other words: I want to loop the reminder-collection and get the same output.

<template name="notworking">
{{#each reminder}}
    {{description}}
    <!-- Here I want the description from the Contract-collection -->
{{/each}}
</template>

corresponding js:

Template.notworking.helpers({
  reminder: function() {
    //?
  }
});
3

There are 3 answers

0
Michel Floyd On BEST ANSWER

You might be better off using Contracts._id to refer to a contract from the Reminders collection that way if the contract name and description change at some point you won't need to update all the related 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 related contract information you'd 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 want to keep your denormalized schema, then the relatedContract function would simply need to return Contracts.findOne({contract: this.contract})

0
saimeunt On

I'm assuming you need to loop over each reminder inside the 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 the reminders will be the currently iterated over contract, so we can access its contract name using this.contract.

As a result you simply need to return every reminders document having the same contract name.

Template.contracts.helpers({
  reminders: function(){
    return Reminders.find({
      contract: this.contract
    });
  }
});
0
sudheer jami On

https://atmospherejs.com/reywood/publish-composite

This package provides flexible way to publish a set of related documents from various collections using a reactive join. Hope it helps.