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>