Last active
February 27, 2020 05:53
-
-
Save LeCoupa/10951713 to your computer and use it in GitHub Desktop.
Meteor: Reactive and Nonreactive Join with MongoDB --> https://github.com/LeCoupa/awesome-cheatsheets
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!-- | |
The examples below illustrate different ways to make a reactive and nonreactive join between two collections. | |
We will retrieve in all of them a list of the 10 most popular posts along with their author profile. | |
More informations are available on: http://journal.gentlenode.com/ | |
Summary: | |
1. Nonreactive Join #1: Denormalization. | |
2. Reactive Join #1: Joining on the client. (by calling a publication) | |
3. Reactive Join #2: Overpublishing. (and joining with data context) | |
4. Reactive Join #3: Using a package to make your publications reactive. (be careful about scalability) | |
--> | |
<!-- 1. Nonreactive Join #1: Denormalization. --> | |
<template name="PostList"> | |
{{#each posts}} | |
<h1>{{title}}</h1> | |
<h2>{{author}}</h2> | |
{{/each}}} | |
</template> | |
<!-- 2. Reactive Join #1: Joining on the client. (by calling a publication) --> | |
<template name="PostList"> | |
{{#each posts}} | |
<h1>{{title}}</h1> | |
<h2>{{author}}</h2> | |
{{/each}} | |
</template> | |
<!-- 3. Reactive Join #2: Overpublishing. (and joining with data context) --> | |
<template name="PostList"> | |
{{#each posts}} | |
<h1>{{title}}</h1> | |
{{#with joinWithAuthor}} | |
<h2>{{author}}</h2> | |
{{/with}} | |
{{/each}} | |
</template> | |
<!-- 4. Reactive Join #3: Using a package to make your publications reactive. (be careful about scalability) --> | |
<template name="PostList"> | |
{{#each posts}} | |
<h1>{{title}}</h1> | |
<h2>{{author}}</h2> | |
{{/each}} | |
</template> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 1. Nonreactive Join #1: Denormalization. | |
// The concept is to denormalize data when you can. | |
// This avoids the need for joins but you need to take care about keeping your data up to date. | |
// This solution can be interesting for scaling your application in situations where the denormalized data do not change very much. | |
// e.g: Post document: { _id: "DdCroCRuXCvNq5vRc", title: "Meteor is Awesome", author: "LeCoupa" } | |
if (Meteor.isServer) { | |
Meteor.publish('getPopularPosts', function() { | |
return Posts.find({ }, { sort: { score: -1 }, limit: 10 }; | |
}); | |
} | |
if (Meteor.isClient) { | |
Template.PostList.created = function() { | |
Meteor.subscribe('getPopularPosts'); | |
} | |
Template.PostList.helpers({ | |
'posts': function() { | |
Posts.find(); | |
} | |
}) | |
} | |
// 2. Reactive Join #1: Joining on the client. (by calling a publication) | |
// We will only publish the post collection to the client. | |
// When the post needs to be displayed, we call a server-side method to grab the author informations. | |
// e.g: Post document: { _id: "DdCroCRuXCvNq5vRc", title: "Meteor is Awesome", userId: "5rNbbGpKDMSiBXF9h" } | |
// Author document: { _id: "5rNbbGpKDMSiBXF9h", author: "LeCoupa" } | |
if (Meteor.isServer) { | |
Meteor.publish('getPopularPosts', function() { | |
return Posts.find({ }, { sort: { score: -1 }, limit: 10 }; | |
}); | |
Meteor.publish('getAuthor', function(userId) { | |
check(userId, Number); | |
return Meteor.users.findOne(userId); | |
}); | |
} | |
if (Meteor.isClient) { | |
Template.PostList.created = function() { | |
Meteor.subscribe('getPopularPosts'); | |
} | |
Template.PostList.helpers({ | |
'posts': function() { | |
Posts.find({ }, { | |
transform: function(doc) { | |
Meteor.subscribe('getAuthor', doc.userId); | |
} | |
}); | |
} | |
'author': function() { | |
return Meteor.users.findOne(this.userId); | |
} | |
}); | |
} | |
// 3. Reactive Join #2: Overpublishing. (and joining with data context) | |
// Sometimes, to avoid to deal with joins, you can decide in a certain situation to publish all the collection documents. | |
// Of course you need to make sure that this will not cause scalability problems inside your application. | |
// e.g: Post document: { _id: "DdCroCRuXCvNq5vRc", title: "Meteor is Awesome", userId: "5rNbbGpKDMSiBXF9h" } | |
// Author document: { _id: "5rNbbGpKDMSiBXF9h", author: "LeCoupa" } | |
if (Meteor.isServer) { | |
Meteor.publish('getPopularPosts', function() { | |
return Posts.find({ }, { sort: { score: -1 }, limit: 10 }; | |
}); | |
Meteor.publish('getEveryAuthors', function() { | |
return Meteor.users.find({ }, { fields: { username: 1 }})); | |
}); | |
} | |
if (Meteor.isClient) { | |
Template.PostList.created = function() { | |
Meteor.subscribe('getPopularPosts'); | |
Meteor.subscribe('getEveryAuthors'); | |
} | |
Template.PostList.helpers({ | |
'posts': function() { | |
Posts.find(); | |
} | |
'joinWithAuthor': function() { | |
var post = this; | |
var author = Meteor.users.findOne(this.userId).username; | |
return _.extend(post, _.omit(author, '_id')); | |
} | |
}); | |
} | |
// 4. Reactive Join #3: Using a package to make your publications reactive. (be careful about scalability) | |
// The reactive-publish package enables reactiviy within Meteor.publish functions. | |
// This causes the entire publication to re-run whenever any of its dependencies change. | |
// Just replace calls to "Meteor.publish" with "Meteor.reactivePublish". | |
// Atmosphere: https://atmospherejs.com/package/reactive-publish | |
// e.g: Post document: { _id: "DdCroCRuXCvNq5vRc", title: "Meteor is Awesome", userId: "5rNbbGpKDMSiBXF9h" } | |
// Author document: { _id: "5rNbbGpKDMSiBXF9h", author: "LeCoupa" } | |
if (Meteor.isServer) { | |
Meteor.reactivePublish('getPopularPostsAndAuthors', function() { | |
var posts = Posts.find({ }, { sort: { score: -1 }, limit: 10 }; | |
var userIds = posts.map(function(doc) { return doc.userId }); | |
var authors = Meteor.users.find({_id: {$in: userIds}} | |
return [ posts, authors ]; | |
}); | |
} | |
if (Meteor.isClient) { | |
Template.PostList.created = function() { | |
Meteor.subscribe('getPopularPostsAndAuthors'); | |
} | |
Template.PostList.helpers({ | |
'posts': function() { | |
return Posts.find(); | |
} | |
'author': function() { | |
return Meteor.users.findOne(this.userId) | |
} | |
}); | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment