Skip to main content

Blog

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: &ldquo;<%= messages[msg].message; %>&rdquo;</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>

Leave a Reply