Using MongooseJS to Create Associations Among MongoDB Collections
Posted on July 21, 2015 in MongoDB, Node.js by Matt Jennings
Below is example code using MongooseJS, other Node.js modules, and a MongoDB database to create associations among MongoDB collections.
package.json
code
{ "name": "messure-board-with-mongoosejs", "version": "0.0.1", "description": "Message Board using MongooseJS", "license": "MIT", "repository": { "type": "git", "url": "https://github.com/Hollyw00d/message-board-with-mongoosejs" }, "scripts": { "start": "node server.js" }, "dependencies": { "body-parser": "1.13.x", "ejs": "2.3.x", "express": "4.13.x", "mongoose": "4.0.x" } }
server.js
code
// Require path var path = require("path"); // Require express and create express app var express = require("express"); var app = express(); // Require body-parser to be able to send POST data var bodyParser = require("body-parser"); app.use(bodyParser.urlencoded( {extended: true} )); // Static content app.use(express.static(path.join(__dirname + "/static"))); // Set up views directory and ejs app.set("views", path.join(__dirname + "/views")); app.set("view engine", "ejs"); // Require mongoose var mongoose = require("mongoose"); // Create/connect to "dojo_message_board" // database mongoose.connect("mongodb://localhost/dojo_message_board"); // Create schema to start associations, // similar to MySQL joins var Schema = mongoose.Schema; var messageSchema = new mongoose.Schema({ name: String, message: String, // Code below creates a // "created_at" date created_at: {type: Date, default: new Date}, // Line below is used to associate // a message "_id" to a // comment "_id" which is // like a foreign key comments: [{type: Schema.Types.ObjectId, ref: "Comment"}] }); var commentSchema = new mongoose.Schema({ // Line below is used to associate // the message "_id" to a comment "_id" // and notice the underscore // in "_message" to associate this "_id" // with the "messageSchema" _message: {type: Schema.ObjectId, ref: "Message"}, name: String, comment: String, // Code below creates a // "created_at" date created_at: {type: Date, default: new Date} }); // "Message" and "Comment" objects below // will give me objects to // take actions on the MongoDB database AND // the "Message" parameter needs to match the 'ref: "Message"' // property value AND // the "Comment" parameter needs to match the 'ref: "Comment"' // property value var Message = mongoose.model("Message", messageSchema); var Comment = mongoose.model("Comment", commentSchema); // Home page app.get("/", function(req, res) { //res.render("index"); // Display all documents from // the "messages" collection on the // home page Message.find({}).populate("comments").exec(function(err, messages) { if(err) { console.log("Error:", err); } else { // Reverses order of properties // in an array of objects messages.reverse(); res.render("index", {messages: messages}); } }); }); // Post message app.post("/messages", function(req, res) { console.log("Message Posted:", req.body); var message = new Message({ name: req.body.name, message: req.body.message }); message.save(function(err) { if(err) { console.log("Error:", err); } else { res.redirect("/"); } }); }); // Post comment using the "_id" field // from the "messages" collection app.post("/message/:id", function(req, res) { // Show post of comment form in terminal console.log("Comment Posted:", req.body); // Code to post one comment related to one // message via the message id Message.findOne( {_id: req.params.id}, function(err, message) { var comment = new Comment(req.body); comment._message = message._id; message.comments.push(comment); comment.save(function(err) { message.save(function(err) { if(err) { console.log("Comment Error", err); } else { res.redirect("/"); } }); }); }); }); // Listen on port 8000 app.listen(8000, function() { console.log("Node.js is running on port 8000"); });
index.ejs
code
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <title>The Dojo Message Board</title> <link rel="stylesheet" type="text/css" href="css/styles.css"/> </head> <body> <div id="wrapper"> <h1>The Dojo Message Board</h1> <hr/> <form id="message-form" action="/messages" method="post"> <p> <label for="name">Name:</label><br /> <input type="text" name="name"/> </p> <p> <label for="message">Message:</label><br /> <textarea name="message"></textarea> </p> <p> <input type="submit" value="Post message"/> </p> </form> <hr/> <% // For in loop to iterate over all // documents in the "messages" // collection from the newest to // oldest message %> <% for(var msg in messages) { %> <div class="message"> <h2>Name: <%= messages[msg].name; %></h2> <h3>Message: “<%= messages[msg].message; %>”</h3> <div class="comment"> <% // Month names in an array var monthName = [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ]; // For loop to // iterate over all // comment(s) of an associated // message %> <% for(var j = messages[msg].comments.length -1; j > -1; j--) { %> <p><strong>Name:</strong> <%= messages[msg].comments[j].name; %><br /><strong>Comment:</strong> <%= messages[msg].comments[j].comment; %><br /> <strong>Date Posted:</strong> <%= messages[msg].comments[j].created_at.getHours(); %>:<%= ("0" + messages[msg].comments[j].created_at.getMinutes()).slice(-2) %>, <%= monthName[messages[msg].comments[j].created_at.getMonth()]; %> <%= messages[msg].comments[j].created_at.getDate(); %>, <%= messages[msg].comments[j].created_at.getFullYear(); %> </p> <% } %> <form class="comment-form" action="/message/<%= messages[msg]._id %>" method="post"> <p><label for="name">Name:</label><br /> <input type="text" name="name"/></p> <p><label for="comment">Comment:</label><br /> <textarea name="comment"></textarea></p> <p><input type="submit" value="Post comment"/></p> </form> </div> <hr /> </div> <% } %> </div> </body> </html>