Skip to main content

Mongoose

Question : What Mongoose is all about?
Answer : Mongoose is an object modeling tool for MongoDB and Node.js. What this means in practical terms is that you can define your data model in just one place, in your code.

Question : Give the example of the basic schema?
Answer : This schema defines the name of each item of data, and the type of data, whether it is a string, number, date, Boolean, and so on.


var userSchema = new mongoose.Schema({
   
name: String,
   
email: String,
   
createdOn: Date,
   
verified: Boolean
})
;


In most scenarios you would have one schema for each collection within the database.
Schemas are a powerful aspect of Mongoose, which can also be extended with helper functions and additional methods. But we'll describe more about that in a later chapter.

Question : What Mongoose is not ideally suited for?

Answer : Mongoose is probably not the answer for you if you are primarily working with the following:
Schema-less data
Random documents
Pure Key-Value pairs

Question : What is MONGOOSE MODELS?

Answer : A model is a compiled version of the schema. One instance of the model will map to one document in the database.
Creating a User instance based on the schema userSchema is a one line task:
var User = mongoose.model('User', userSchema);
It is the model that handles the reading, creating, updating, and deleting of documents.
Question  : How to connect to the database?
Answer : The way to set the default connection to a MongoDB database via Mongoose is nice and easy, using the mongoose.connect method.
var dbURI = 'mongodb://localhost/mydatabase';
mongoose.connect(dbURI);

This will open a Mongoose connection to the Mongo database mydatabase, running on the server localhost. If established at the correct place in your code, this connection will now be available at any point in your app, if you require Mongoose.
Question : What is the best practice for Using multiple connections
Answer : The default connection is great if your app only needs to connect to one database. But what happens if you need to connect to a second database at the same time? Or connect to the same database as a different user with different permissions.
For this we can use the mongoose.createConnection method, which is as follows in the code snippet:
var dbURI = 'mongodb://localhost/myadmindatabase';
var
adminConnection = mongoose.createConnection(dbURI);
Question : How to specify the port
Answer : The default port is 27017. If you wanted to specify a different port, say 27018, you would do so using the following code snippet:
var dbURI = 'mongodb://localhost:27018/mydatabase';
Question : How to Specify a database user name with the connection string.
Answer : If you want to access the database as a particular user, you can add the username and password in front of the hostname.
var dbURI = 'mongodb://username:password@localhost/mydatabase';
Question : What are the diffrent Connection options?
Answer : Mongoose allows you to pass certain options through to both connection methods. If specified, these options will override those set in the connection string.
The options are sent as a JSON object as an optional second parameter to the connection call. For example:
var dbURI = 'mongodb://localhost/mydatabase';
var
dbOptions = {'user':'db_username','pass':'db_password'};
mongoose.connect(dbURI, dbOptions);
The options you can use this way are:
user and pass: Username and password for the database, if required and not specified in the connection string.
db: This relates to the DB options available in the Node MongoDB Native driver.
server: This relates to the server options available in the Node MongoDB Native driver.
replset: This option allows you to specify a ReplicaSet. The details of ReplicaSet methods are beyond the scope of this book, but the principle is that you can have one primary database where all the writes are made to, and multiple secondary databases. If the primary database fails, one of the secondary databases is automatically made the new primary.

Question : How to close the mongoose connection 

Answer : This by calling the close command, Each Mongoose connection has a close() method that takes an optional callback function.

If you are using the default connection you call it like the following code snippet does:

mongoose.connection.close(function () {
   
console.log('Mongoose default connection closed');
});


Calling the close() method on a named connection is just as easy, using our example from earlier:
adminConnection.close(function () {
   
console.log('Mongoose connection adminConnection closed');
});


Question : How can we Close when the Node process ends
Answer : As a rule you should tide up the connections when your Node application stops, whether this is an intentional process termination or not. To do this, you can send your disconnections as a callback to Node's process.on('SIGINT') event as shown in the following:


process.on('SIGINT', function() {
   
mongoose.connection.close(function () {
       
console.log('Mongoose disconnected through app termination');
       
process.exit(0);
   
});
});


Question : List Connection events.
Answer: The connection process in Mongoose inherits the Node EventEmitter class, meaning that we can set certain code to run following specific events. We can—and will—work with some of the connection events, such as connected, disconnected, and error.

The connection events are all used in the same way, sending a callback to the connection.on event listener. For example, if we wanted to log to the console when a connection error occurs we could do this in the following code:



mongoose.connection.on('error',function (err) {
   
console.log('Mongoose connection error: ' + err);
});


Question : Give a code example of above?
Answer :
/** * Created by vcmishra on 8/27/17. */
const mongoose = require("mongoose");
let connection;
const disconnected = 'disconnected';
const connected = 'connected';
const connecting = 'connecting';
const disconnecting = 'disconnecting';
const unauthorized = 'unauthorized';
const uninitialized = 'uninitialized';

const connect = (uri) => {
mongoose.connect(uri, () => {
console.log("initializing the connection");
        console.log("status ", mongoose.connection._readyState);
        mongoose.connection.on('open', function () {
connection = mongoose.connection;
        });
    })

mongoose.connection.on(disconnected, function () {
console.log("Disconnected");
    });
    mongoose.connection.on(connected, function () {
connection = mongoose.connection;
        console.log(connected);
    });
    mongoose.connection.on(connecting, function () {
console.log(connecting);
    });
    mongoose.connection.on(disconnecting, function () {
console.log(disconnecting);
    });
    mongoose.connection.on(uninitialized, function () {
console.log(uninitialized);
    });
}

const getConnection = () => {
return connection;
}

const getConnectionStatus = () => {
return connection._readyState;
}

const listCollections = () => {
connection.db.listCollections().toArray(function (err, names) {
if (err) {
console.log(err);
        } else {
console.log(names);
        }

});
}

module.exports = {connect, getConnection, listCollections, getConnectionStatus}

Question : Do we have any limit on document size in mongodb?

Answer : MongoDB imposes a maximum document size of 16 MB. There are ways around even this limit, using the MongoDB GridFS API.

Question : What are Data types allowed in schemas

Answer : There are eight types of data that can—by default—be set in a Mongoose schema. These are also referred to as SchemaTypes; they are:
String
Number
Date
Boolean
Buffer
ObjectId
Mixed
Array
Question : How can we Track changes for the mixed data type.
Answer : As Mongoose can't automatically see changes made to mixed type of data, you have to manually declare when the data has changed. Fortunately, Mongoose exposes a method called markModified to do just this, passing it the path of the data object that has changed.
dj.mixedUp = { valueone: "a new value" };
dj.markModified('mixedUp');
dj.save();

Warning – array defined as mixed typeA word of caution. If you declare an empty array it will be treated as mixed type, meaning that Mongoose will not be able to automatically detect any changes made to the data. So avoid these two types of array declaration, unless you intentionally want a mixed type.

var emailSchema = new mongoose.Schema({  addresses: []});
var emailSchema = new mongoose.Schema({  addresses: Array});

Question : What's that "__v" thing?

Answer : You may have noticed a data entity in the document that we didn't set: __v. This is an internal versioning number automatically set by Mongoose when a document is created. It doesn't increment when a document is changed, but instead is automatically incremented whenever an array within the document is updated in such a way that might cause the indexed position of some of the entries to have changed.
When working with an array you will typically access the individual elements through their positional index, for example, myArray[3]. But what happens if somebody else deletes the element in myArray[2] while you are editing the data in myArray[3]? Your original data is now contained in myArray[2] but you don't know this, so you quite happily overwrite whatever data is now stored in myArray[3].The __v gives you a method to be able to sanity check this, and prevent this scenario from happening.

Question : How to allow unique entries?

Answer : we need to specify the unique : true
e.g.
email: {type: String, unique:true}

Question : How can we create model from the Schema?

Answer : Building the model, as we have seen, is pretty straightforward. When using the default Mongoose connection we can call the mongoose.model command, passing it two arguments:

The name of the model

The name of the schema to compile
So if we were to build a model from our user schema we would use this line:


const User  = mongoose.model( 'User', userSchema );

Question : How to create the instance from the model?

Answer : We have to use new operator to create the object of the model.
var userOne = new User({ name: 'Simon' });
const userOne = new User({ name: 'Simon' });

Question : How to save the data, in the mongo db using the instance of the model?

Answer : As each new User is an instance of the model, we are able to use the power of the model to save it to the database as shown in the following code:


const userOne = new User({ name: 'Simon' });const userTwo = new User({ name: 'Sally' });

userTwo.save(function (err) {
   
if (err) return handleError(err);
   
// userTwo (Sally) is saved!
});
userOne.save(function (err) {
   
if (err) return handleError(err);
   
// userOne (Simon Holmes) is saved!
});

Question : What is the difference between mongoose model create and mongoose new model and then calling save function?

Answer : below is the example of new and then save.
var newUser = new User({name: 'Simon Holmes'})
newUser.
email = 'simon@theholmesoffice.com';
var
rightNow = Date.now();
newUser.createdOn = rightNow;
newUser.lastLogin = rightNow;
// some more operations on newUser
newUser.save( function( err, user ){
   
if(!err){
       
console.log('_id of saved user: ' + user._id);
   
}
})
;
below is the example of the mongoose model create

User.create({

   
name: 'Simon Holmes',
email: 'simon@theholmesoffice.com',
   
lastLogin: Date.now()
}
, function (err, user) {
   
if (!err) {
       
console.log('User saved!');
       
console.log('Saved user name: ' + user.name);
       
console.log('_id of saved user: ' + user._id);
   
}
})
;
This is arguably the neater way of doing a brand new create and save operation, and is the approach we'll be using in our MongoosePM application later. The cost of the compact nature of this approach is that it is less flexible, as we can't do anything with the newUser instance between creating it and saving it. If you need this flexibility, then go for the new and save approach.

Question : What is the signature of the find Method?

Answer : Model.find(conditions, [fields], [options], [callback]);
In this construct, fields and options are both optional, but if you want to specify options then you must specify fields, even if you send it as null.
Mongoose will run the callback function when the operation has been completed. If no callback function is defined then the query will not be executed. It can however be called explicitly by using the .exec() method we saw earlier.
User.find(
    {
'name' : 'Simon Holmes'}, // users called Simon Holmes
   
null, // returning all fields in model [fields]
   
{sort : {lastLogin : -1}}, // sorted by lastLogin descending [options]
   
function (err, users){
       
if (!err){console.log(users);}
    })
;

Question : What are the different methods to update a document/record in mongo using mongoose?

Answer : There are three static methods for updating data in a single go:
update(): This method updates matching documents in the database without returning them
findOneAndUpdate(): This method has the same approach as findOne that we looked at earlier, but writes the updates to the database before returning the found instance to the callback
findByIdAndUpdate(): This method is the same as findOneAndUpdate, but expects a unique ID instead of query object.
Each of these methods can take the following four arguments:
conditions: These are the query conditions (or _id for findByIdAndUpdate) used to find documents to update
update: This is an object containing the fields and values to set
options: This is an object specifying options for this operation (see more details about this in just a moment)
callback: This is the function to run after a successful operation.

Question : From above there is options optional argument, what are the possible values it supports?

Answer : for the update() options are as follows:
safe: Specifies whether errors should be returned to the callbacks. Can be true or false, the default value is the value set in the schema, if this was not explicitly set in the schema it defaults to true.
upsert: Specifies whether to create the document if no matching document exists. Can be true or false, the default value is false.
multi: Specifies whether multiple documents should be updated. Can be true or false, the default value is false.
strict: Specifies whether only data defined in the schema will be saved, regardless of whether anything additional was passed to the model constructor. Can be true or false, the default value is true.
The options for the findByIdAndUpdate() and findOneAndUpdate() methods are as follows:
new: Specifies whether to return the modified document rather than the original. Can be true or false, the default value is true.
upsert: Specifies whether to create the document if it doesn't exist. Can be true or false, the default value is false.
sort: If some documents are found, sets the sort order to choose which one to update. This should be a JavaScript object.
select: This sets the document fields to return. This is specified as a string.

Question : What are the validator options we have with the mongoose.

Answer : 1. required :  There is one validator that can be used by any SchemaType, named required. This will return a validation error if no data is given to a data object with this property.
e.g. email: { type: String, unique: true, required: true }
2. min and max : Number items in your schema have built-in min and max validators, for declaring lower and upper boundaries.
e.g. age : {type: Number, min: 13, max:19}.
3. match: This validator is for matching against a regular expression.
var weekdaySchema = new Schema({  day : {type: String, match: /^(mon|tues|wednes|thurs|fri)day$/i}});
4. enum: This validator is for checking against a provided list of possible values
var weekdays = ['monday', 'tuesday', 'wednesday', 'thursday', 'friday'];
var
weekdaySchema = new Schema({  day : {type: String,  enum: weekdays}});


Question : What is pre and post hooks?
Answer : Plugins also have access to all of the middleware available to schemas. There are two types of middleware hooks:
pre: This middleware is for before the method has completed
post: This is for after the method has completed
e.g.

var mongoose = require( 'mongoose' );
module.exports = exports = function modifiedOn (schema, options) {
    schema.
add({ modifiedOn: Date });
   
schema.pre('save', function (next) {
       
this.modifiedOn = Date.now();
       
next();
   
});
};

This will do two things, which are:
Add the modifiedOn path with a SchemaType of Date then Set the value to be the current date and time just before the document is saved. This removes the need to manually set the value each time we run an update operation on any of the schemas.





Comments

Popular posts from this blog

NodeJS

Question : Why You should use Node JS? Answer :  Following are the major factor influencing the use of the NodeJS Popularity : The popularity can be important factor, as it has more user base and hence solution  of any common problem faced by developer can found easily online, without any professional help. JavaScript at all levels of the stack :  A common language for frontend and backend offers several potential benefits: The same programming staff can work on both ends of the wire Code can be migrated between server and client more easily Common data formats (JSON) exist between server and client Common software tools exist for server and client Common testing or quality reporting tools for server and client When writing web applications, view templates can be used on both sides Leveraging Google's investment in V8 Engine. Leaner, asynchronous, event-driven model Microservice architecture Question : example of node JS code? Answer :  const fs = require('fs'); co...

Javascript

Question : example of Map Reduce Answer : (() => { let aNumberArray = [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ] ; let sum = aNumberArray. map (data => data * 2 ) . reduce ((ongoing , data) => ongoing + data) ; console . log (sum) ; })() Question : What is IIFE? Answer  : Immediately Invoked function expression e.g. (function(){}()). usually pronounces as " effy ". Question : Why the script tag should be added at the bottom or before the end of the body tag? Answer  : It helps the html page to render quickly without even downloading the script which may be getting downloaded from the slow CDN. there are other alternative like async and defer as well, which are supported primarily on new browsers.     <script src="bower_components/angular/angular.min.js" defer></script>     <script src="bower_components/jquery/dist/jquery.min.js" defer></script>     <script src="bower_components...

HTML&CSS

Question : Why title element is important? Answer : This is the element represent, html page in the tab, also when you add this webpage as a bookmark then it will be a default name saved for the bookmark name. Question : What is the benefit of using the label? Answer : the for attribute of lable tag will able to associate the name with the element, and clicking on the label itself is good enough to add the focus and and selection to the given element. Question : Does the box-sizing property affect the overall width or height of the elements? Answer : Yes, border width, padding and margin is added to the width properties, e.g. h1 { line-height : 40 px ; font-weight : bold ; color : aqua ; font-size : 40 px ; width : 300 px ; padding : 50 px ; margin : 50 px ; border : 10 px dotted ; text-align : center ; } This means that the overall of width of the element is width value  + 2 * padding [ right + left ] + 2 * border [ left + right ]. Questio...