I am new to Mongo and NoSQL databases. Can someone explain the way to do a one to many join and a cycling through collections in Meteor.
For example, say I have two collections, a Post and a Comment where each comment has a postId, meaning each Post has zero or many Comments. I am interested in what would be best practice for this type of situation for Meteor specifically where you can cycle through each post and comment in a nested Handlebars call. Something like the example below:
{{#each post}}
{{title}}
{{content}}
{{#each comment}}
{{comment_text}} by {{author}}
{{/each}}
{{/each}}
Although the standard MongoDB paradigm is to denormalize data, in Meteor applications it's not uncommon to stick to the pattern of having different collections (tables) for each logical dataset.
To implement joins in Meteor webapps, you simply have to define a relation between the two collections :
var postId = Posts.insert({
title: "A post",
content: "Some content..."
});
Comments.insert({
postId: postId,
author: "Someone",
text: "Some text..."
});
Denormalizing means that you must not forget to publish the two collections, you can do as follow :
Meteor.publish("postById", function(postId){
// publish the according post...
var postCursor = Posts.find(postId);
// ...and every comments associated
var commentsCursor = Comments.find({
postId: postId
});
// you can return multiple cursors from a single publication
return [postCursor, commentsCursor];
});
This publication would send down to the client a post and all its comments, given a post._id
.
Associated with correct client-side routing, you can subscribe to this publication with the post id retrieved from a URL (/posts/:_id
) and display the post with all its comments.
Your template pseudo code is OK, however I would refactor it using a distinct template for each collection.
HTML
<template name="outer">
{{!-- loop through each post, the child template will
be using the current post as data context --}}
{{#each posts}}
{{> post}}
{{/each}}
</template>
JS
Template.outer.helpers({
posts: function(){
return Posts.find();
}
});
HTML
<template name="post">
<h3>{{title}}</h3>
<p>{{content}}</p>
{{!-- loop through each comment and render the associated template --}}
{{#each comments}}
{{> comment}}
{{/each}}
</template>
JS
Template.posts.helpers({
comments: function(){
// return every comment belonging to this particular post
// here this references the current data context which is
// the current post being iterated over
return Comments.find({
postId: this._id
});
}
});
HTML
<template name="comment">
<p>{{text}}</p>
<span>by {{author}}</span>
</template>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With