cover
MongoDBDatabaseNoSQL

MongoDB

Cover
https://1000logos.net/wp-content/uploads/2020/08/MongoDB-Logo.jpg
Slug
MongoDB
Published
Published
Date
Jan 16, 2024
Category
MongoDB
Database
NoSQL
  • MongoDB stores data in flexible, JSON-like documents
  • The document model maps to the objects in your application code, making data easy to work with
  • MongoDB is a distributed database at its core, so high availability, horizontal scaling, and geographic distribution are built in and easy to use
— BEST FOR ECOMMERSE + STARTUP & APPS like Snapchat or Instagram who need near by location of people

mongosh

show dbs use test show collections db.dropDatabase() cls exit
test>>db.users.insertOne({name: "John"}) //add json to users collection in test database db.users.find() //find all in users collections //nested field db.users.insertOne({ name: "Sally", age: 19, address: { street: "987 North St" }, hobbies: ["Running"] }) db.new.insertMany([{name:"mike"},{name:"jill"}]) //multiple insertion
db.new.find().limit(1) //limit no. of result db.new.find().sort({name: -1}) //sorting assending(1) or desending(-1) db.new.find().sort({age: 1,name: -1}) db.new.find().skip(1).limit(1) // can skip also db.new.find({name: kyle}) db.new.find({name: "Sally"}, {name: 1, age: 1}) //if i only want name,age db.new.find({name: "Sally"}, {name: 1, age: 1,_id:0}) //if i only want name,age also i don't want id db.new.find({name: "Sally"}, {age: 0}) //all fields except age db.users.find({ name: { $eq: "Sally" }}) //shell + DB (equal = eq) // shell include ne,gt,lt,gte,lte db.users.find({ name: { $in: ["Sally","robin"] }}) // similarly has nin - not in db.users.find({ age: { $exists: true }}) //only objects that have age db.users.find({ name: { $gte: 20, $lte:25 }}) //two condition db.users.find({ age: { $gte: 20, $lte: 40 }, name: "Sally" }) //multi condition db.users.find({ $and: [{age: 26 }, { name: "Kyle" }] }) //and operation need array //also can have or , not db.users.find({ age: { $not: { $lte: 20 } }}) // not
$ sign before column
>>db.users.insertMany([{ name: "Tom", balance: 100, debt: 200 }, { name: "Kristin", balance: 20, debt: 0}]) >> db.users.find({$expr: { $gt: ["$debt", "$balance"]} })
db.users.find({ "address.street": "123 Main St" }) db.users.countDocuments({ age: { $lte: 40 }})

Update

$set - to update property
db.users.updateOne({age: 26}, { $set: { age: 27 } }) db.users.updateOne({ _id: ObjectId("6112809d7ec144c25156c4dd")}, { $set: { name: "New Name" } }) //increment db.users.updateOne({ _id: ObjectId("6112809d7ec144c25156c4dd") }, { $inc: { age: 3 }}) //change the name of property db.users.updateOne({ _id: ObjectId("6112809d7ec144c25156c4dd") }, { $rename: { name: "firstName" }}) //remove perticular property db.users.updateOne({ _id: ObjectId("6112809d7ec144c25156c4dd") }, { $unset: { age: ' } }) //add new property db.users.updateOne({ _id: ObjectId("6112809d7ec144c25156c4dd") }, { $push: { hobbies: "Swimming" } }) //remove perticular data from property db.users.updateOne({ _id: ObjectId("6112809d7ec144c25156c4dd") }, { $pull: { hobbies: "Bowling" } }) db.users.updateMany({address: {$exists: true}},{$unset: {address: ""}}) //replace everything at location & delete all and add new one db.users.replaceOne({age: 30},{name:"john"}) //delete db.users.deleteOne({ name: "John" }) //deleteMany db.users.deleteMany({ age: { $exists: false} })
 
 









Mongoose

Mongoose is an Object Data Modeling (ODM) library for MongoDB and Node.js. It manages relationships between data, provides schema validation, and is used to translate between objects in code and the representation of those objects in MongoDB.

Schema

A Mongoose schema is a document data structure (or shape of the document) that is enforced via the application layer.
const puppySchema = new mongoose.Schema({ name: { type: String, required: true }, age: Number });

Models

Models are higher-order constructors that take a schema and create an instance of a document equivalent to records in a relational database.
const Puppy = mongoose.model('Puppy', puppySchema);

NPM Install

npm init -y npm install mongoose validator

Database Connection

Database class into a singleton by returning an instance of the class in the module.exports statement because we only need a single connection to the database.
let mongoose = require('mongoose'); const server = '127.0.0.1:27017'; // REPLACE WITH YOUR DB SERVER const database = 'fcc-Mail'; // REPLACE WITH YOUR DB NAME class Database { constructor() { this._connect(); } _connect() { mongoose .connect(`mongodb://${server}/${database}`) .then(() => { console.log('Database connection successful'); }) .catch((err) => { console.error('Database connection error'); }); } } module.exports = new Database();

Validator library

validation function that will ensure that the value is a valid email address.
let mongoose = require('mongoose'); let validator = require('validator'); let emailSchema = new mongoose.Schema({ email: { type: String, required: true, unique: true, lowercase: true, validate: (value) => { return validator.isEmail(value); } } }); module.exports = mongoose.model('Email', emailSchema);

Create Record

create an instance of the email model and save it to the database
let EmailModel = require('./email'); let msg = new EmailModel({ email: 'ADA.LOVELACE@GMAIL.COM' }); msg .save() .then((doc) => { console.log(doc); }) .catch((err) => { console.error(err); });
>>>>Result
{ _id: 5a78fe3e2f44ba8f85a2409a, email: 'ada.lovelace@gmail.com', __v: 0 }
  1. __v is the version Key property set on each document when first created by Mongoose. Its value contains the internal revision of the document.
  1. The _id field is auto-generated by Mongo and is a primary key of the collection. Its value is a unique identifier for the document

Fetch Record

EmailModel.find({ email: 'ada.lovelace@gmail.com' // search query }) .then((doc) => { console.log(doc); }) .catch((err) => { console.error(err); });

Update Record

EmailModel.findOneAndUpdate( { email: 'ada.lovelace@gmail.com' // search query }, { email: 'theoutlander@live.com' // field:values to update }, { new: true, // return updated doc runValidators: true // validate before update } ) .then((doc) => { console.log(doc); }) .catch((err) => { console.error(err); });

Delete Record

EmailModel.findOneAndRemove({ email: 'theoutlander@live.com' }) .then((response) => { console.log(response); }) .catch((err) => { console.error(err); })

Helpers

create a user schema
let mongoose = require('mongoose'); let userSchema = new mongoose.Schema({ firstName: String, lastName: String }); module.exports = mongoose.model('User', userSchema);

Virtual Property

create a virtual property called fullName which can be used to set values on firstName and lastName and retrieve them as a combined value when read
userSchema.virtual('fullName').get(function () { return this.firstName + ' ' + this.lastName; }); userSchema.virtual('fullName').set(function (name) { let str = name.split(' '); this.firstName = str[0]; this.lastName = str[1]; });
>>>>>
let model = new UserModel(); model.fullName = 'Thomas Anderson'; console.log(model.toJSON()); // Output model fields as JSON console.log(); console.log(model.fullName); // Output the full name
>>>>> result
{ _id: 5a7a4248550ebb9fafd898cf, firstName: 'Thomas', lastName: 'Anderson' } Thomas Anderson

Instance Methods

create a function to return the initials for the current user. Let’s add a custom helper method called getInitials to the schema
userSchema.methods.getInitials = function () { return this.firstName[0] + this.lastName[0]; };
let model = new UserModel({ firstName: 'Thomas', lastName: 'Anderson' }); let initials = model.getInitials(); console.log(initials); // This will output: TA

Static Methods

we can create static methods on the schema. Let’s create a method to retrieve all users in the database
userSchema.statics.getUsers = function () { return new Promise((resolve, reject) => { this.find((err, docs) => { if (err) { console.error(err); return reject(err); } resolve(docs); }); }); };
getUsers on the Model class will return all the users in the database

Middleware

Middleware are functions that run at specific stages of a pipeline
operations:
  • Aggregate
  • Document
  • Model
  • Query
For instance, models have pre and post functions that take two parameters:
  1. Type of event (‘init’, ‘validate’, ‘save’, ‘remove’)
  1. A callback that is executed with this referencing the model instance
 
example - adding two fields called createdAt and updatedAt to our schema
let mongoose = require('mongoose'); let userSchema = new mongoose.Schema({ firstName: String, lastName: String, createdAt: Date, updatedAt: Date }); module.exports = mongoose.model('User', userSchema);
When model.save() is called, there is a pre(‘save’, …) and post(‘save’, …) event that is triggered. For the second parameter, you can pass a function that is called when the event is triggered. These functions take a parameter to the next function in the middleware chain.
userSchema.pre('save', function (next) { let now = Date.now(); this.updatedAt = now; // Set a value for createdAt only if it is null if (!this.createdAt) { this.createdAt = now; } // Call the next function in the pre-save chain next(); });
let UserModel = require('./user'); let model = new UserModel({ fullName: 'Thomas Anderson' }); msg .save() .then((doc) => { console.log(doc); }) .catch((err) => { console.error(err); });

Plugins

Suppose that we want to track when a record was created and last updated on every collection in our database. Instead of repeating the above process, we can create a plugin and apply it to every schema.
create a plugin for timestamp
module.exports = function timestamp(schema) { // Add the two fields to the schema schema.add({ createdAt: Date, updatedAt: Date }); // Create a pre-save hook schema.pre('save', function (next) { let now = Date.now(); this.updatedAt = now; // Set a value for createdAt only if it is null if (!this.createdAt) { this.createdAt = now; } // Call the next function in the pre-save chain next(); }); };
To use this plugin, we simply pass it to the schemas that should be given this functionality:
let timestampPlugin = require('./plugins/timestamp'); emailSchema.plugin(timestampPlugin); userSchema.plugin(timestampPlugin);

Query Building

Consider a query where we can incrementally build query components.
UserModel.find() // find all users .skip(100) // skip the first 100 items .limit(10) // limit to 10 items .sort({ firstName: 1 }) // sort ascending by firstName .select({ firstName: true }) // select firstName only .exec() // execute the query .then((docs) => { console.log(docs); }) .catch((err) => { console.error(err); });