I'm starting to learn Mongoose and I have a question.
In the documentation there are many places where we create a schema with new Schema
syntax. For example:
var blogSchema = new Schema({
title: String,
author: String,
//other fields
});
and then use it:
var Blog = mongoose.model('Blog', blogSchema);
But on the Mongoose's main page there is an example without it. We just put an object as a second argument of mongoose.model
:
var Cat = mongoose.model('Cat', { name: String });
What is Schema
class used for? What is the difference of this two approaches?
Do you want to re-use the schema somewhere else? Do you also realize that abstracting embedded statements lead to cleaner code?
The main difference is re-use where you want to actually do that. The second difference is that a separate declaration is generally easier to read and understand.
This is really more of a "coding style" question, and therefore to try and keep it away from "voicing and opinion" only I am largely pointing out the "re-use" point.
Another factor to consider is that all of these things are really just object constructors it does not mean you need to use it that way as a "hardcoded" approach. Consider loading all schema and model information from a "config file" for example:
As a config file:
{
"Schema": {
"ownerSchema": {
"name": { "type": "String" },
"email": { "type": "String" },
"accounts": [{ "type": "ObjectId", "ref": "Account" }]
},
"transactionSchema": {
"account": { "type": "Number" },
"added": { "type": "Date" }
},
"recentBucketSchema": {
"_id": { "type": "ObjectId", "ref": "AccountBucket" },
"day": { "type": "Date" }
},
"accountSchema": {
"owner": { "type": "ObjectId", "ref": "Owner" },
"balance": { "type": "Number", "default": 0 },
"recent": [{ "schema": "recentBucketSchema" }]
},
"accountBucketSchema": {
"day": { "type": "Date" },
"account": { "type": "ObjectId", "ref": "Account" },
"owner": { "type": "ObjectId", "ref": "Owner" },
"balance": { "type": "Number", "default": 0 },
"transactions": [{ "schema": "transactionSchema" }]
}
},
"Models": {
"Owner": { "schema": "ownerSchema" },
"Account": { "schema": "accountSchema" },
"AccountBucket": { "schema": "accountBucketSchema" }
}
}
And as a processor:
var async = require('async'),
fs = require('fs'),
mongoose = require('mongoose'),
Schema = mongoose.Schema;
function ReturnType(type) {
switch(type) {
case "String":
return String;
case "Number":
return Number;
case "Date":
return Date;
case "ObjectId":
return Schema.Types.ObjectId;
}
}
function ParseSchema(schema,data) {
for ( k in schema ) {
var outerType = Object.prototype.toString.call( schema[k] );
if ( outerType !== "[object Array]" ) {
schema[k].type = ReturnType(schema[k].type);
} else {
if ( schema[k][0].hasOwnProperty("schema") ) {
schema[k][0] = ParseSchema(data.Schema[schema[k][0].schema],data)
} else {
schema[k][0].type = ReturnType(schema[k][0].type);
}
}
}
return new Schema( schema );
}
async.waterfall(
[
function(callback) {
var file = __dirname + '/sample.json';
fs.readFile(file, 'utf8', function(err,data) {
if (err)
callback(err);
callback(err,JSON.parse(data));
});
},
function(data,callback) {
async.each( Object.keys( data.Models ), function(modelName,callback) {
var currentSchema = data.Schema[data.Models[modelName].schema];
currentSchema = ParseSchema(currentSchema,data);
mongoose.model( modelName, currentSchema );
callback();
},function(err) {
callback();
});
}
],
function(err) {
if (err)
throw err;
}
);
Just a basic example, but there is a clear reason for the general separation as in the way you can actually use it.
So if your question really is "Why are there two ways to do it?", then I can say for one that there are actually many ways to do it and not just two. Frameworks and libraries should not "lock you in" to a specific way of doing things. They should be free to use in the way that suits you best.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.