Defining the schema and models

For the purposes of the application we are building, we're really only going to have two different unique schemas and associated models: an image model and comment model. If we were to take this application to production and really build it out with all of the necessary features, we should expect to have many more models as well.

First, create a new directory in your project labeled models and we will store the Node.js modules for each of our models here. Create three files in this directory named image.js, comment.js, and index.js. Let's take a look at the image model first. Copy the following block of code into the models/image.js file:

var mongoose = require('mongoose'),
    Schema = mongoose.Schema,
    path = require('path'),

var ImageSchema = new Schema({
    title:          { type: String },
    description:    { type: String },
    filename:       { type: String },
    views:          { type: Number, 'default': 0 },
    likes:          { type: Number, 'default': 0 },
    timestamp:      { type: Date, 'default': Date.now }
});

ImageSchema.virtual('uniqueId')
    .get(function() {
        return this.filename.replace(path.extname(this.filename), ''),
    });

module.exports = mongoose.model('Image', ImageSchema);

First, we define our ImageSchema with the various fields that we are going to want to store in MongoDB for each of the images. We created a virtual property of uniqueid, which is just the filename with the file extension removed. As we want our Image model to be available throughout the rest of our app, we export it using module.exports. Note that we are exporting the model not the schema (as the schema itself is fairly useless to us). Let's set up a similar model for comments. Copy the following block of code into the models/comment.js file:

var mongoose = require('mongoose'),
    Schema = mongoose.Schema,
    ObjectId = Schema.ObjectId;

var CommentSchema = new Schema({
    image_id:   { type: ObjectId },
    email:      { type: String },
    name:       { type: String },
    gravatar:   { type: String },
    comment:    { type: String },
    timestamp:  { type: Date, 'default': Date.now }
});

CommentSchema.virtual('image').set(function(image){
        this._image = image;
    }).get(function() {
        return this._image;
    });

module.exports = mongoose.model('Comment', CommentSchema);

There are a few important things to take note of with this model. First, we have a field labeled image_id, which has an ObjectId type. We're going to use this field to store the relationship between a comment and the image that it was posted to. The ObjectId that gets stored in this field is the _id of the related image document from MongoDB.

We also define virtual on the comment schema labeled image, which we provide a getter and setter for. The image virtual property will be how we attach the related image when we retrieve comments later in our controllers. For every comment, we are going to iterate through and look up its associated image and attach that image object as a property of the comment.

Note

It's important to understand how Mongoose and MongoDB handle the naming of collections based on your schema and models. Typically, you name your models using singular terms, and Mongoose will recognize this and create your collections using a pluralized model name. So, a model defined as Image will have a collection in MongoDB named images. Likewise, a model named Comment will have a corresponding collection named comments. Mongoose tries to be smart about this; however, a model defined as Person will have a corresponding collection named people and so on. (And yes, octopus will result in octopi!)

Models index file

There's one last file in the models folder that we haven't yet touched on in our project. The index.js file within any folder in Node.js acts as an index file for the modules within it. This is by convention, so you don't have to adhere to this if you don't want to.

Since our models folder will contain a number of different files, each a unique module for one of our models, it would be nice if we could just include all of our models in a single require statement. Using the index.js file we can do so pretty easily too. Copy the following block of code into the models/index.js file:

module.exports = {
    'Image': require('./image'),
    'Comment': require('./comment')
};

The index.js file inside the models directory simply defines a JavaScript object that consists of a name-value pair for each module in our directory. We manually maintain this object, but this is the simplest implementation of the concept. Now, thanks to this basic file, we can perform require('./models') anywhere in our application and know that we have a dictionary of each of our models via that module. To reference a specific model in that module, we simply refer to the specific model as a property of the module. If we only wanted to require a specific model somewhere in our app instead, we can perform require('./models/image') just as easily! You will see more of this a little later and it will become much more clear.

Because our two models are so closely related, we are typically always going to require the models dictionary using require('./models') throughout our application.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.142.197.212