Mongoose - Defining a model for a preexisting collection - node.js

I have imported some CSV data to my database through mongoimport, which created my collection during the import.
When defining my model in Node, what do I pass for the schema parameter? Viewing my db in compass shows a schema already created based off the imported data.
I'm currently passing an empty schema which seems totally wrong.
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var Units = new Schema({
});
module.exports = mongoose.model('Units', Units, 'units');

The schema should contain something like this that defines the kind of data you're working with.
var Units = new Schema({
f_name: String,
l_name: String,
manager: Boolean
});
See 'Defining your schema'.
Also, I don't believe mongoose.model takes a third parameter.
module.exports = mongoose.model('Units',Units);
Edit: yes it does.

Related

Create schema on mongoose whether to use 'new' keyword or not?

I understand what is the use of Schema and model in mongoose, however when defining/creating a new Schema there are 2 ways of doing it (that I found of), and I'm confused by it,
1st way (without new - no instance created):
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/dbName');
// No 'new' keyword
var mySchema = mongoose.Schema({
parameter1 : String,
parameter2 : String
});
var modelName = mongoose.model('collectionName', mySchema);
and 2nd way of doing it (with new - an instance created):
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/dbName');
// There is 'new' keyword
var mySchema = new mongoose.Schema({
parameter1 : String,
parameter2 : String
});
var modelName = mongoose.model('collectionName', mySchema);
What's the differences between the two? when to use one or the other?
Both way are fine, but according to code standard and mongoose library, we use 2nd way. It's follow extending & Implementation feature like OOP.
Schema & Model we use in nodejs for validation & restrict unwanted object & fields inserting into mongo collection.
Thats the reason for uses.

How to use a mongoose model defined in a separate file if the file is not exported?

Consider a very simple Express 4 app structure:
-- app.js
-- models
|--db.js
|--news.js
where news.js contains a mongoose schema and a model based on that schema:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var newsSchema = new Schema({
title: String,
subtitle: String,
// other fields...
});
var News = mongoose.model('News', newsSchema);
To my understanding, in order for app.js to use the News model, it has to require the file within the script like this: require('./models/news'). Also, news.js would have to export the model like this: module.exports = News;.
However, I have come across a number of scripts that do not export models (or anything for that matter) defined in a separate file while still be able to use those models and/or schema in a different file just by requiring the model file and then do something like this:
var mongoose = require('mongoose');
var News = mongoose.model('News');
How is this behavior possible? It is a special feature of Mongoose? How can a file use a model or schema defined in another file if that model/schema is not exported within that file?
This ultimately works because when you call require('mongoose') in various files, you get back the same object. In other words: it gets shared between app.js and news.js, in your case.
When you create a new model (using mongoose.Model('Name', schema)), Mongoose stores that model instance in an internal list of models.
This also allows you to get an instance by name, using mongoose.Model('Name'). Mongoose will look up that model in its internal list, and return it.

How to clone Mongoose schema?

I am working on Mongoose plugin that have to access existing model and create similar schema as previous model and fix some attributes and add some custom properties. How to do such cloning of scheme? I tried but its not working:
var mongoose = require('mongoose');
var mainSchema = new mognoose.schema({'prop' : String});
var anotherSchema = new mongoose.schema(mainSchema);
Of course, its not working at all and I can't find any solution in API doc and source code (as far I can read that code).
For anyone googling, try:
schema.clone();
This creates a full copy of the schema, so you can add more properties, multiple discriminators, etc.
http://mongoosejs.com/docs/api.html#schema_Schema-clone
Assign the schema to a regular object first:
var mongoose = require('mongoose');
var schemaObj = {'prop' : String}
var mainSchema = new mongoose.Schema(schemaObj);
var anotherSchema = new mongoose.Schema(schemaObj);

Confused about Mongoose/Mongo Terminology. Are Sub-Docs/Embedded-Docs also Collections?

If I have the following mongoose models:
// child.model.js
var mongoose = require('mongoose'),
Schema = mongoose.Schema,
childSchema = new Schema({
name: String,
age: Number
}, {collection: 'children'});
module.exports = mongoose.model('Child', childSchema);
//parent.model.js
var mongoose = require('mongoose'),
Child = require('./child.model.js'),
Schema = mongoose.Schema,
parentSchema = new Schema({
name: String,
children: [Child.schema]
});
module.exports = mongoose.model('Parent', parentSchema);
Would this mean I would then have two collections, one called 'parents' and one called 'children'?
As I currently understand it the above code creates a nested document structure whereby the Child objects exist only within the collection of Parent documents. However, I'm getting confused by the {collection: 'name'} option that you can pass to the Schema constructor. Is this option just ignored when creating sub-documents like this?
There are two kinds of subdocs - Embedded and Referenced. This is a Mongoose-level classification. At MongoDB level it's just Collections and Documents.
The difference between Embedded and Referenced docs in Mongoose is that the former is akin to having the child schema "embedded" in the parent. I.e. as far as MongoDB is concerned it (Parent) is just a one big document.
Whereas in referenced docs the Parent document only stores the child document's ObjectID, i.e. the child document is "referenced", and it's left up to you to "populate" the entire document.
What you're using children: [Child.schema] is the syntax of an Embedded document.
Would this mean I would then have two collections, one called 'parents' and one called 'children'?
So you'll have only 1 collection in MongoDB.
However, I'm getting confused by the {collection: 'name'} option that you can pass to the Schema constructor. Is this option just ignored when creating sub-documents like this?
That option is just so that if you were to actually create a model from that schema, it uses the name you provided instead of automatically inferring.

Getting all documents from MongoDB instead of all Models

I'm calling MongoDB from my Node app using Mongoose like this:
var query = itemModel.find();
query.exec(function (err, items) {
console.log(err);
socket.emit("items", items);
});
I have 3 models defined like this:
var Schema = mongoose.Schema
, ObjectId = Schema.ObjectId;
var playerModel = require('./models/player.js').make(Schema, mongoose);
var characterModel = require('./models/character.js').make(Schema, mongoose, ObjectId);
var itemModel = require('./models/item.js').make(Schema, mongoose);
my models look like this:
function make(Schema, mongoose) {
itemSchema = new Schema({
name: String
, bonus: [{
type: String
, value: Number
}]
, price: Number
, slot: String
});
return mongoose.model('Character', characterSchema);
}
exports.make = make;
For some reason I'm getting all documents, regardless of them being items, characters or players. Since I'm calling find() on itemModel I was expecting only Items, what am I doing wrong?
The model that you have shown appears to be the item model, but you are creating the model with the 'Character' name. This means that you told Mongoose about the scheme for an item and that it is stored in the 'character' collection. Assuming you've done the same for each other model (Character/Player), you've been Mongoose that everything is in the same collection.
Then you query that collection and you seem surprised that everything is stored in the same collection. It strikes me as if you have little experience with Mongoose/MongoDB, so I will suggest you download and learn to love MongoVUE. This application is a good GUI to see what is going on under the hood of the MongoDB database. While developing, you also might want to enable debugging so you can see what queries mongoose is launching to the server (mongoose.set('debug', true)).

Resources