Database
Why Use DB
- DB can handle large amounts of data effectively and store it compactly.
- DB provide tools for easy insertion, querying, and updating of data.
- DB generally offer security features and control over access to data.
- DB (generally) scale well.
SQL vs. NoSQL Databases
SQL | NoSQL |
Structured Query Language | Do not use SQL. (Newer, diverse group) |
Relational DB : Can relate tables, often by referencing one another | There are many types of NoSQL DB, including document, key-value, and graph stores. |
Pre-define a schema of tables before any data is inserted | More Flexible |
EX) MySQL, Postgres, SQLite, Oracle, Microsoft SQL Server | EX) MongoDB, CouchDB, Neo4j, Cassandra, Redis |
MongoDB
- A general perpose, document-based, distributed database.
- Why Mongo
- Mongo is very commonly used with Node anad Express
- MEAN stack : Mongo-Express-Angular-Node
- MERN stack : Mongo-Express-React-Node
- Easy to get started with
- Plays particularly well with JS
- Strong community of developers using Mongo
- Mongo is very commonly used with Node anad Express
- Document ⊂ Collection ⊂ Database
- Basic Mongo Shell Commends
- db : prints current database
- show dbs : prints a list of all databases on the server
- use <db> : switch current database to <db>. If <db> doesn't exist, creates one.
BSON
- Binary JSON
- Issuses with JSON
- JSON can be slow since it is text-based. (Parsing text is very slow)
- JSON's readable format is not space-efficient.
- JSON supporst a limited number of basic data types.
- BSON looks like JSON, but MongoDB stores it as binary, making it to be parsed much more quickly.
Inserting
- If the collection doesn't exist when a DB is inserted, insert operations will create the collection.
- Documents don't have to follow the same pattern.
- Syntax : db.collection.insert();
- Example
db.cats.insert({name: 'Monji', age: 3}); //collection 'cats' created
db.cats.find(); //gives {"_id" : ObjectId("String"), "name" : "Monji", "age" : 3}
//"_id" : Primary key created by Mongo.
//ObjectId : A particular type in Mongo
Finding
- Selects document sin a collection or view and returns a cursor to the selected documents.
- Syntax
- db.collection.find() : find all the documents from the collection.
- db.collection.find(query, projection)
- Example
db.dogs.find({"catFriendly" : true})
//Finds all the dogs that are cat friendly.
Updating
- Select document and change the contents
- Syntax
- db.collection.updateOne(<filter>, <update>, <options>)
- db.collection.updateMany(<filter>, <update>, <options>)
- <filter> : query
- <update> : $<update operator>: {key : value}
- Can use multiple update operators at once.
- Example
db.cats.updateOne({name:"Monji"}, {$set: {age:5}})
//Monji's age changed from 3 to 5
Replace
- Conpletely replaces the document with another one. (Primary key unchanged)
- Syntax : db.collection.replaceOne(<filter>, <update>, <options>)
Delete
- Syntax
- db.collection.deleteOne(query)
- db.collection.deleteMany(query)
- Example
- db.dogsdeleteMany({isAvailable: false})
Additional Mongo Operators
- How to find nested properties
//Example
{
"personality" : {"catFriendly": true, "childFriendly": true}
}
db.dogs.find({'personality.catFriendly': true});
- Query Operators
- Comparison Operators
- $gt : greater than
- $gte : greater than or equal to
- $in : in an array
- $lt : less than
- $lte : less than or equal to
- $eq : equal to
- $ne : not equal to
- $nin : not in an array
- Logical Operators
- $and
- $not
- $nor
- $or
- Array Operators
- $all : all arrays containing all queries inside.
- $elemMatch : select documents if elements in the qrray field matches all the specified $elemMatch conditions.
- $size : select documents if the array field is a specified size.
- Comparison Operators
//Comparison Operators Example
db.inventory.find({qty: {$gt: 20}});
db.dogs.find({age: {$lt: 10}});
db.dogs.find({breed: {$in: ['Mutt', 'Corgi']}});
//Logical Operators Example
db.dogs.find({$or: [{'personality.catFreindly': true}, {'age': {$lte: 2}}]})
Mongoose
ODM
- Object Data Mapper / Object Document Mapper
- ↔ ORM (for SQL) : Object Relational Mapper
- Map documents comming from a database into usable JavaScript objects
- [Mongoose] provides ways for us to model out our application data and define a schema. It offers easy ways to validate data and build comples queries from the comfort of JS.
What Mongoose does
- Connects MongoDB & JS(Node.js)
- Makes working with MongoDB easier.
- Make Mongo data into JS objects.
How to connect Mongoose
- Node : npm i mongoose
- index.js
const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost:27017/DBname', {useNewUrlParser: true, useUnifiedTopology: true});
.then(() => {
//code
})
.catch(e => {
//code
console.error(e);
})
//connect : returns a promise
//DBname : Name of DB. If it doesn't exist, it will be created.
Model
- JS class that represents information in a Mongo database or collection.
- "Models" the information coming back from MongoDB.
- Helps interacting with information in the DB & sending new information to the DB, etc.
- How to Model
- Creates a Schema
- Each Schema maps to a MongoDB collection and defines the shape of the documents within the collection.
- Maps collection keys from MongoDB to different types.
- Schema Types : String, Number, Date, Buffer, Boolean, Mixed, ObjectId, Array, Decimal128, Map
- Pass the Schema into the Model
- Create a Document
- Creates a Schema
//Example
//1. Create a Schema
const kittySchema = new mongoose.Schema({
name: String
});
//2. Pass the Schema into the Model
const Kitty = mongoose.model('Kitty', kittySchema);
//First argument of mongoose.model has to be Capitalized & Singular
//Model name: Kitty, Collection name : kitties
//3. Create a Document
const yoji = new Kitty({name: "Yoji"});
yoji.save(); //saved to the DB
//in Mongo,
//use cats
//db.kitties.find() : gives "Yoji"
Model.insertMany()
- Works like Mongo's insertMany()
- Returns a promise (No need to save)
- Example
Movie.insertMany([
{title:'Amelie', year: 2001},
{title:'Alien', year: 1979},
{title:'The Iron Giant', year: 1999}
]).then(data => {
console.log(data); //data: movie objects
}).catch(e => {
console.error(e)
})
Model.find()
- Returns Mongoose queries.
- Not promises, but thenable objects
- Have .then() function.
- Works like Mongo's find()
- exec()
- Returns promise.
- Example
try {
await Movie.fine({title: 'Amadeus'}).exec();
} catch (e => console.error(e))
- Model.findById()
- Syntax : await Model.findById(id).exec()
Update with Mongoose
- Model.updateOne()
- Updates the first one of matching documents
//Example
Movie.updateOne({title: 'Amadeus}, {year: 1984})
.then(res => console.log(res)) //Updates Amadeus' year to 1984
- Model.updateMany()
- Update all the matching documents
- Model.findOneAndUpdate()
- Syntax: Model.findOneAndUpdate(query, update)
- options
- passed in as third argumetn
- new: boolean. If true, returns the modified document, not the original.
- Example : Model.findOneAndUpdate({title: 'Amadeus'}, {score: 7}, {new: true})
Deleting with Mongoose
- Methods for Delete
- Model.remove(query) : deprecated
- Model.removeOne(query) : Doesn't give deleted document
- Model.removeMany(query)
- Model.findOneAndDelete(query) : Gives deleted document back
Mongoose Schema Validations
- Schema values' properties. (SchemaType Options)
- Criteria for input
- Example
const kittySchema = new mongoose.Schema({
name : {
type : String //If not String, throws an error
required : true //If name is not included, throws an error
}
});
Schema Constraints
- All Types
- required
- default : sets default value
- String
- lowercase/uppercase
- trim
- minlength/maxlength
- enum : checks if the String input exists in the array
- Number
- min/max
Validating Mongoose Updates
- When updating the data, Mongoose doesn't validate the data. Thus, invalid data might get stored.
- To avoid this, set the option 'runValidators' as true.
- Example
Product.findOneAndUpdate({name: 'true'}, {price: 19.99}, {new: true, runValidators: true});
Validation Error Message
- The second argument of each validator is the error message.
- It has to be String.
- Example
const productSchema = new mongoose.Schema({
price : {
type: Number,
required: true,
min: [0, 'Price must be positive']
}
})
Model Instance Methods
- Adding custom methods to Schemas : Defining or adding functionality onto the model
- Instance Method : Available on every single instance
- Class/Static Method : available only from the class
- How to define instance methods
- Define a Schema
- Assign a function to the "methods" object of the Schema
//Example1
let animalSchema = new Schema({name: String, type: String});
animalSchema.methods.findSimilarTypes = function(cd) {
return mongoose.model('Animal').find({type: this.type}, cb);
}
//findSimilarTypes : name of method
//function has to be a traditional function, NOT an arrow function.
//Example2
productSchema.methods.addCategory = function (newCat) {
this.categories.push(newCat);
return this.save();
}
- How to defind static methods
- Assign a function to the "statics" object of the Schema
- Or, call "Schema.static()"
//Example
animalSchema.statics.findByName= function(name) {
//code that finds animal by its name
}
animalSchema.static('findByBreed', function(breed) {
//code that finds animal by its breed
})
productSchema.statics.fireSale = function() {
return this.updateMany({}, {onSale: true, price: 0})
}
Mongoose Virtuals
- Gives the ability to add properties to a Schema that doesn't actually exist in the database itself.
- get method : Reads the database to return something else.
- set method : Update the database using the virtual from get method.
// Example
const personSchema = new mongoose.Schema({
first: String,
last: String
})
personSchema.virtual('fullname').get(function() {
return `${this.first} ${this.last}`
//'fullname' doesn't exist in the database, but acts like a property.
}).set(function(v) {
this.name.first = v.substr(0,v.indexOf(' ');
this.name.last = v.substr(v.indexof(' ')+1);
//When used for 'tom = {first: 'Tom', last: 'Cruise'}'
//'tom.fullName = "Tom Hanks"'
//updates the database to 'tom = {first: 'Tom', last: 'Hanks'}'
})
Mongoose Middleware
- Also called pre and post hooks.
- functions that are passed control during excution of asynchronous functions.
//Example
personSchema.pre('save', async fucntion() {
console.log('About to save'); //runs before save()
})
personSchema.post('save', async function() {
console.log('Just saved'); //runs after save()
})
* This post is a summary of Udemy Course "The Web Developer Bootcamp" by Colt Steele.
'TIL: Today I Learned' 카테고리의 다른 글
[TIL] 20201219 Handling Errors in Express Apps (0) | 2020.12.19 |
---|---|
[TIL] 20201218 Middleware: The Key To Express (0) | 2020.12.19 |
[TIL] 20201216 Express / Dynamic HTML with Templating / RESTful Routes (0) | 2020.12.16 |
[TIL] 20201215 The Terminal / Our First Brush with Node / Exploring Modules & The NPM (0) | 2020.12.15 |
[TIL] 20201214 Prototypes, Classes & OOP (0) | 2020.12.14 |