Back End
Back End
*Web servers
*Database engineering
Front-end Arquitecture
Client side makes resquests, and back-end gives response to those requests to the client side.
Back-end Arquitecture
APIs = (how data is exchanged between a database and any app accessing it)
Middleware (APIs)
Let client-server talk and provides services (like data integration and error handling). Also maximize IT
efficiency and power things (like user engagement, business process management, content
management, authentication, etc.)
What is HTTP?
1 Why HTTP
2 DNS
3 URIs
4 Async
5 Errors
6 Headers, Body
7 JSON
9 Paths
10 HTTPS
REST
Websockets
GraphQL
MySQL
Redis
6 Deploy some projects to your professional portfolio
Node.js
Server environment, uses js on the server.
*create, open, read, write, delete and close files on the server
Export modules
Install Packages
npm install <packageName> - -save to include dependency in the package.json of the app
npm install <pN> -g to include packages globally, independent of the current path.
Modules
Libraries, a set of functions to include in the app
Built-in Modules
Include Modules
Require(“mod_name”)
Require(“./mod_name”) to include own module, exported from a file
HTTP Module
Allows to transfer data over Hyper Text Transfer Protocol. require(“http”)
Creates an HTTP server that, listens to server ports and, gives response back to client
Web Server
.createServer(function).listen(8080) creates a server object that, listens on port 8080. Practically web
server is to access web pages of an app. It returns Request(url, header, data, etc.) and Response objects
.writeHead(200, {‘Content-Type’: ’text/html’}) 200, all’s ok. {} object containing the response header.
http.createServer(function(req, res){
})
.url prop which holds the part of the url that comes after the domain name
http.createServer(function(req, res){
res.end(txt);
}).listen(8080)
File System Module
allows to work with the file system on the computer. Read, create, update, delete and rename files.
Include
Require(‘fs’)
Read files
.readFile(‘fileName’, function)
.readFileSync(‘fileName’, ‘utf8’) to read the file synchronously, returns the file data
Var fs = require(“fs”);
http.createServer(function(req, res){
res.write(data);
return res.end();
});
}).listen(8080)
Create Files
*.appendFile(‘fileNme’, ‘content’, function) appends specified content to a file, case it doesn’t exist
then it’s auto created.
Var fs = require(‘fs’);
})
*.writeFile() like the prior but, replaces the specified content case it exists. Case it doesn’t, a new file
with the specified content is auto created.
*.open(‘fileName’, ‘flag’, function) takes a flag, ‘w’ or ‘r’, case it doesn’t exist an empty file’s created.
Var fs = require(‘fs’);
})
Update Files
Delete Files
*.unlink(‘fileName’, function)
Event Loop
runs in a single-threaded event-driven model. Observers executes once the event is fired.
Methods
.once() happens the next time it’s called then, gets removed.
.removeListener()
.setMaxListeners(nº) / .getMaxListeners()
Blocking I/o
Debugging
With core debugger, node inspector, IDE built-in debugger.
Core debugger
*cont as next, to continue & stop only at next debugger (if any).
*watch(‘exp’) / watchers as next, to add values into watch / to see the values at watch.
Node inspector
Run it
Start debugging
Web server
Configure routes
Above app object has get(), post(), put() n delete() methods to define routes 4 HTTP GET, POST, PUT n
DELETE requests.
Res.send(‘<html><body><h1>Hello World</h1></body></html>’)
}) ‘/’ the path of a route dat’ll start after base URL. Ftion callback wit request n response objects dat’ll
run on each get resquest.
Res.send(‘POST Request’)
})
App.put(‘/update-data’, ftion(req, res){
Res.send(‘PUT Request’)
})
Res.send(‘DELETE Request’)
})
Npm install body-parser the middleware to handle HTTP POST resquest. It parses the JSON, buffer, str
n url encoded data submitted.
Res.sendFile(‘formFile.html’)
});
Res.send(name + ‘Submitted!’);
})
Express.static() u just have to specify the folder name where u’ve stored ur static resources.
App.use(express.static(_ _dirname + ‘Public’)); // Serves resources from public folder. Use() mounts the
middleware express.static for every request.
App.use( ‘/images’, express.static(_ _dirname + ‘Images’)); use() mounts for evy request that start wit
‘/images’. Serves all the request which includes /images in the url from Images folder, can also create a
virtual path.
The node-static module is an HTTP static-file server module wit built-in caching.
http.createServer(ftion(req, res){
fileserver.serve(req, res);
}).listen(5000);
Data Access in Node.js
Node.js supports all kinds of databases. However NoSQL dbs best fit wit it.
Npm i mysql to access a db from Node.js u first need to install its driver.
Npm i mssql, to access relational db MSSQL Server 2012 in Node.js app using Express.js
//connect to ur database
Sql.connect(config, ftion(err){
if(err) console.log(err);
Res.send(recordset);
})
})
Connecting MongoDB
//connect to the db
Inserting Documents
db.collection(‘Persons’).count(ftion(err, count)){
})
})
Update/Dalete Documents
});
});
})
Query Database
collection.find().toArray(ftion(err, items){
});
Req.method, req.path, req.ip to get the http method, path n caller’s ip of a request that reaches a
route.
Route parameters
req.params.name
sth/:name/eco
Query parameters
route_path: '/library'
actual_request_URL: '/library?userId=546&bookId=6754'
req.query: {userId: '546', bookId: '6754'}
Mongoose is a popular npm package for interacting with MongoDB. With Mongoose,
you can use plain JavaScript objects instead of JSON, which makes it easier to work
with MongoDB. Also, it allows you to create blueprints for your documents called
schemas, so you don't accidentally save the wrong type of data and cause bugs later.
schema maps to a mongodb collection. Defines shape of documents in dat collection. Building blocks
for Models
Fields
Schema While Mongo is schema-less, SQL defines a schema via the table definition. A Mongoose
‘schema’ is a document data structure (or shape of the document) that is enforced via the application
layer.
Model are higher-order constructors that take a schema and create an instance of a document
equivalent to records in a relational database.
npm install mongoose validator Let’s install Mongoose and a validation library with the following
command
./src/database.js
class Database {
constructor() {
this._connect()
}
_connect() {
mongoose.connect(`mongodb://${server}/${database}`)
.then(() => {
console.log('Database connection successful')
})
.catch(err => {
console.error('Database connection error')
})
}
}
a simple class with a method that connects to the database. Your connection string will vary based on
your installation.
A Mongoose model provides an interface to the database for creating, querying, updating, deleting
records, etc.
1. Referencing Mongoose
This reference will be the same as the one that was returned when we connected to the database,
which means the schema and model definitions will not need to explicitly connect to the database.
A schema defines document properties through an object where the key name corresponds to the
property name in the collection.
email: String
})
Here we define a property called email with a schema type String which maps to an internal validator
that will be triggered when the model is saved to the database. It will fail if the data type of the value is
not a string type.
Array, Boolean, Buffer, Date, Mixed (A generic / flexible data type), Number, ObjectId, String.
3. Exporting a Model
We need to call the model constructor on the Mongoose instance and pass it the name of the collection
and a reference to the schema definition.
Basic Operations
Mongoose has a flexible API and provides many ways to
accomplish a task. We will not focus on the variations because
that is out of scope for this article, but remember that most of
the operations can be done in more than one way either
syntactically or via the application architecture.
Create Record
Let’s create an instance of the email model and save it to the
database:
msg.save()
.then(doc => {
console.log(doc)
})
.catch(err => {
console.error(err)
})
Fetch Record
Let’s try to retrieve the record we saved to the database earlier.
The model class exposes several static and instance methods
to perform operations on the database. We will now try to find
the record that we created previously using the find method and
pass the email as the search term.
EmailModel
.find({
email: '[email protected]' // search query
})
.then(doc => {
console.log(doc)
})
.catch(err => {
console.error(err)
})
Update Record
Let’s modify the record above by changing the email address
and adding another field to it, all in a single operation. For
performance reasons, Mongoose won’t return the updated
document so we need to pass an additional parameter to ask
for it:
EmailModel
.findOneAndUpdate(
{
email: '[email protected]' // search query
},
{
email: '[email protected]' // 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
We will use the findOneAndRemove call to delete a record. It
returns the original document that was removed:
EmailModel
.findOneAndRemove({
email: '[email protected]'
})
.then(response => {
console.log(response)
})
.catch(err => {
console.error(err)
})
Helpers
We have looked at some of the basic functionality above known
as CRUD (Create, Read, Update, Delete) operations, but
Mongoose also provides the ability to configure several types of
helper methods and properties. These can be used to further
simplify working with data.
Virtual Property
A virtual property is not persisted to the database. We can add
it to our schema as a helper to get and set values.
userSchema.virtual('fullName').set(function(name) {
let str = name.split(' ')
this.firstName = str[0]
this.lastName = str[1]
})
Callbacks for get and set must use the function keyword as we
need to access the model via the this keyword. Using fat arrow
functions will change what this refers to.
Now, we can set firstName and lastName by assigning a value
to fullName:
let model = new UserModel()
Instance Methods
We can create custom helper methods on the schema and
access them via the model instance. These methods will have
access to the model object and they can be used quite
creatively. For instance, we could create a method to find all the
people who have the same first name as the current instance.
Static Methods
Similar to instance 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)
})
})
}
Calling getUsers on the Model class will return all the users in
the database:
UserModel.getUsers()
.then(docs => {
console.log(docs)
})
.catch(err => {
console.error(err)
})
Adding instance and static methods is a nice approach to
implement an interface to database interactions on collections
and records.
Middleware
Middleware are functions that run at specific stages of a
pipeline. Mongoose supports middleware for the following
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’)
2. A callback that is executed with this referencing the model instance
this.updatedAt = now
// Set a value for createdAt only if it is null
if (!this.createdAt) {
this.createdAt = now
}
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.
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:
emailSchema.plugin(timestampPlugin)
userSchema.plugin(timestampPlugin)
Query Building
Mongoose has a very rich API that handles many complex
operations supported by MongoDB. Consider a query where we
can incrementally build query components.
Model.create([ {}, {}, {} ], (err, data)=>{ done(null, data)}) create many docs at once
findOneAndUpdate()
{ new: true } as the 3rd argument to return the updated doc.
.sort({ name: -1 })
.limit(5)
.select({ favoriteFoods: 0 })
.exec(function(error, people) {
//do something here
});
App.all() special routing method called to any HTTP method.
router.get(“/”, …)
router.get(“/”, …)
module.exports = router; Route handlers for all Wiki of the site in Wiki.js. made with express.Router.
&
// …
App.use(“/wiki”, wiki) to use it in our main app file, we used use() to add the Router to the
middleware handling path.