How to clone Mongoose schema? - node.js

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);

Related

Mongoose - Defining a model for a preexisting collection

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.

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 can I generate an ObjectId with mongoose?

I'd like to generate a MongoDB ObjectId with Mongoose. Is there a way to access the ObjectId constructor from Mongoose?
This question is about generating a new ObjectId from scratch. The generated ID is a brand new universally unique ID.
Another question asks about creating an ObjectId from an existing string representation. In this case, you already have a string representation of an ID—it may or may not be universally unique—and you are parsing it into an ObjectId.
You can find the ObjectId constructor on require('mongoose').Types. Here is an example:
var mongoose = require('mongoose');
var id = mongoose.Types.ObjectId();
id is a newly generated ObjectId.
Note: As Joshua Sherman points out, with Mongoose 6 you must prefix the call with new:
var id = new mongoose.Types.ObjectId();
You can read more about the Types object at Mongoose#Types documentation.
You can create a new MongoDB ObjectId like this using mongoose:
var mongoose = require('mongoose');
var newId = new mongoose.mongo.ObjectId('56cb91bdc3464f14678934ca');
// or leave the id string blank to generate an id with a new hex identifier
var newId2 = new mongoose.mongo.ObjectId();
I needed to generate mongodb ids on client side.
After digging into the mongodb source code i found they generate ObjectIDs using npm bson lib.
If ever you need only to generate an ObjectID without installing the whole mongodb / mongoose package, you can import the lighter bson library :
const bson = require('bson');
new bson.ObjectId(); // 5cabe64dcf0d4447fa60f5e2
Note: There is also an npm project named bson-objectid being even lighter
With ES6 syntax
import mongoose from "mongoose";
// Generate a new new ObjectId
const newId2 = new mongoose.Types.ObjectId();
// Convert string to ObjectId
const newId = new mongoose.Types.ObjectId('56cb91bdc3464f14678934ca');

Nested models mongoose with nodejs generates duplicates

here is my code for models.js where I keep models
var mongoose = require('mongoose')
, Schema = mongoose.Schema;
var GroupSchema = new Schema({
title : String
, elements : [ElementSchema]
, author : String
});
var ElementSchema = new Schema({
date_added : Date
, text : String
, author : String
});
mongoose.model('Group', GroupSchema);
exports.Group = function(db) {return db.model('Group');};
mongoose.model('Element', ElementSchema);
exports.Element = function(db) { return db.model('Element');
};
To me it looks pretty clear, but when I do
function post_element(req, res, next) {
Group.findOne({_id: req.body.group}, function(err, group) {
new_element = new Element({author: req.body.author,
date_added: new Date()});
new_element.save();
group.elements.push(new_element);
group.save();
res.send(new_element);
return next();
})
}
I don't understand why when I go in Mongo I have two collections one called Groups with nested groups (so it looks fine) and the other collection is called Elements.
Why? Shouldn't it be called just Group ?
I don't understand, a good chap that please explain it to me?
Thanks,
g
When you execute this line:
new_element.save();
you're saving the newly created element to the Elements collection. Don't call save on the element and I think you'll get the behavior you're looking for.
Its because of the following line:
mongoose.model('Element', ElementSchema);
This registers a model in mongoose and when you register a model, it will create its own collection inside mongo. All you have to do is get rid of this line and you will see it disappear.
On another note, its much cleaner and easier to setup your files to only export one model per file using the following to export the model:
module.exports = mongoose.model('Group', GroupSchema);
Hope this helps!

Resources