Using Node JS

paste bin: some interesting examples

My first script in nodejs
What does not work in nodejs?
Built in values and functions
Some characteristics of functions in Javascript
Built in modules
Creating and Importing modules
Creating and Importing a module - "destructuring"
Create a class and export it as a module
Using fs (file system module) - Read from a file
Node.js as a Web Server
Node.js as a Web Server - add web header
Using fs (file system module) - Read from a file - file not found
Using fs (file system module) - Read from a file - file not found and print error
Using fs (file system module) - Read from a file - file not found catch with process.on
Using fs (file system module) - Read from a file - use path module
Using fs (file system module) - Write to file
Using fs (file system module) - Append to file
Using fs (file system module) - Append to delete file
Synchronous vs Asynchronous methods
Async programing: read, write, delete, append
Inefficient use of node server - blocks server for 5 seconds
More efficient use of node server
createReadStream and createWriteStream
Using NPM
Using date-fns
UUID
Is node js multi-threaded?
demonstrates libuv and OS Async Helpers
Create a LogEvent Module
Create a simple web server
Create a web server and server home page and REST API
Using node with Express JS
Node and MongoDB: connecting to database, Creating one or Multiple Records
Node and MongoDB: find multiple documents
Node and MongoDB: Updating a single Document
Node and MySql

myfirst script in nodejs

 
const amount = 12;

if (amount < 10){
	console.log('small number');
	}
else{
	console.log('big number');
}
console.log('hello world!');

output in console

PS C:\data\node> node first_node_pgm.js
-or-
PS C:\data\node> node first_node_pgm
big number
hello world!

What does not work in nodejs?

 
// What does not work in nodejs?

// Node.js is is a stand-alone JavaScript environment completely independent of a web browser.  There's no 
// intrinsic link between web browsers and JavaScript; the DOM and window objects are not part of the JavaScript language 
// or specification or anything.

// As a result anything related to window object (window, document,screen, navigator, cookie) will not work.

// console.log(window.innerWidth);
// console.log(window.innerHeight);
// console.log(window.location.href);
// document.cookie = "username=John Doe"; 
// console.log(screen.height);
// console.log(navigator.cookieEnabled);
// window.alert("hello world");
   alert("hello world");

output on console

ReferenceError: window is not defined

Built in values and functions

	
// __dirname
// __filename
// require - function to use modules
// module - info about current module
// process - info about environment where process is being executed

console.log(__dirname);
console.log(__filename);
console.log(module);
console.log(process);

4 ways to Declare variables in Javascript

1. var : The var scope is global when a var variable is declared outside a function. This means that any variable that is declared with var outside a function block is available for use in the whole window. The var variables can be re-declared and updated. This can be a problem as your code grows. The var variable is hoisted by javascript engine. It is initialized as undefined,

2. let: let is block scoped. It is only available for use within that block. let can be updated but not re-declared. let keyword is not initialized automatically.

3. const Like let declarations, const declarations can only be accessed within the block they were declared. const cannot be updated or re-declared. const declarations are hoisted to the top but are not initialized.

4. The variables declared without the var keyword becomes global variables. to be avoided


Some characteristics of functions in Javascript

 


// Some characteristics of functions in Javascript

// reference: https://www.telerik.com/blogs/four-ways-to-create-a-function-in-javascript

// 1. A function as a statement
function Add_v1(num1,num2){
    let sum = num1+ num2; 
    return sum; 
}
let answer_v1 = Add_v1(7,8);
console.log("1.function as statement", answer_v1);   // = 15

// 2. A function as a statement (part 2)
// Javascript lets us use function before declaring it. Javascript will "hoist" function definition to the top
let answer_v2 = Add_v2(7,8);
console.log("2.function as statement with hoisting", answer_v1);   // = 15

function Add_v2(num1,num2){
    let sum = num1+ num2; 
    return sum; 
}

// 3. function as expression
let add_v3 = function a(num1,num2){
    let sum = num1+ num2; 	
    return sum;
}

let answer_v3 = add_v3(10,20);
console.log("3.function as expression", answer_v3);   // = 30


// 4. function using arrow operator
var add_v4 = (num1, num2)=> num1+num2; 
let answer_v4 = add_v4(3,5);
console.log("4.function using arrow operator", answer_v4);  // = 8


// 5. A function as a statement returning an object
function getProduct(){
    let product = {
        Id:1,
        Title:'Book',
        Price: 30
    };
    return product; 
}
let p1 = getProduct();
console.log("5. function returning an object", p1); // { Id: 1, Title: 'Book', Price: 30 }

output


1.function as statement 15
2.function as statement with hoisting 15
3.function as expression 30
4.function using arrow operator 8
5. function returning an object { Id: 1, Title: 'Book', Price: 30 }


Built in modules

 
console.log("Hello World");
console.log('directory name is ' +__dirname);
console.log('file name is ' + __filename);

// use built-in path module 
const path = require('path')
console.log( path.parse(__filename));
console.log('path of filename is ' + path.dirname(__filename));
console.log('basename is ' + path.basename(__filename));
console.log('extension of file is ' + path.extname(__filename));

// use built-in os module 
const os = require('os');
console.log('OS type is ' + os.type());
console.log('OS platform is ' + os.platform);
console.log('OS version is ' + os.version());
console.log('Home Directory is ' +  os.homedir());
output:
Hello World
directory name is C:\data\node\NewFolder    
file name is C:\data\node\NewFolder\index.js
{
  root: 'C:\\',
  dir: 'C:\\data\\node\\NewFolder',
  base: 'index.js',
  ext: '.js',
  name: 'index'
}
path of filename is C:\data\node\NewFolder  
basename is index.js
extension of file is .js
OS type is Windows_NT
OS platform is win32
OS version is Windows 10 Home
Home Directory is C:\Users\itp
PS C:\data\node\NewFolder>

Creating and Importing modules

In Node.js, Modules are the blocks of encapsulated code that communicates with an external application on the basis of their related functionality. Modules can be a single file or a collection of multiples files/folders. Modules permit re-usability as well as the ability to break down a complex piece of code into manageable chunks. Every file is a module in node.js

The keyword to export = module.export
The keyword to use module = require('./file'). Note that if any code is executed in a module, then it will be executed when require is called.

// we have create 5 functions inth math.js, but export only 4 (add, subtract, multiply, divide)

var theAnswerIs = (value)  =>  "The answer is " + value  ;
const add = (a,b) => theAnswerIs(a+b);
const subtract = (a,b) => theAnswerIs(a - b); 
const multiply = (a,b) => theAnswerIs(a * b); 
const divide = (a,b) => theAnswerIs(a / b); 

module.exports = {add, subtract, multiply, divide}

// Using a module. Use "require" to import module
// file: math_example_01.js
const math = require('./math')
console.log(math.add(100,100))
console.log(math.subtract(100,50))
console.log(math.multiply(100,3))
console.log(math.divide(100,20))

// This last one should fail because theAnswerIs() function was not imported.
// theAnswerIs() function is hidden because it is not exported.
// Note that if we remove the var keyword, it will word, but we probably don't want to expose it like this. 

//console.log(theAnswerIs(5));

output:

The answer is 200
The answer is 50
The answer is 300
The answer is 5


Creating and Importing a module - "destructuring"

The destructuring assignment syntax is a JavaScript expression that makes it possible to unpack values from arrays, or properties from objects, into distinct variables.

// this is a module
// file: math.js
const add = (a,b) => a+b 
const subtract = (a,b) => a - b 
const multiply = (a,b) => a * b 
const divide = (a,b) => a / b 

module.exports = {add, subtract, multiply, divide}
// how we use custom module
// file: math_example_01.js
const {add} = require('./math')
console.log(add(1,1))

Create a class and export it as a module

file person.js

// file person.js
// here we create class called Person and export it as a module

//  Note: Before a module's code is executed, Node.js will wrap it with a function wrapper that looks like the following:
//  (function(exports, require, module, __filename, __dirname) { 
//    Module code actually lives in here 
//  }); 



class Person {
    constructor(name,age) {
        this.name = name;
        this.age = age;
    }

   

    greeting(){
        console.log(`My name is ${this.name} and I am ${this.age}` );
        }
    }

module.exports = Person;

// node: node js makes some additional variables available:
console.log(__dirname, __filename);

file index.js


// here we create class called Person and export it as a module

const Person = require('./person');

// this alternative syntax coming soon with "ES6 Modules" 
// import Person  from './person';

const person1 = new Person('John Doe', 30);

person1.greeting();

Using fs (file system module) - Read from a file

// use fs, the file system module
const fs = require('fs')
fs.readFile('./starter.txt', 'utf8', (err,data) =>{
if (err) throw err;
    console.log(data);
})

Node.js as a Web Server

The HTTP module can create an HTTP server that listens to server ports and gives a response back to the client. Use the createServer() method to create an HTTP server:

var http = require('http');

//create a server object:
http.createServer(function (req, res) {
  res.write('Hello World!'); //write a response to the client
  res.end(); //end the response
}).listen(8080); //the server object listens on port 8080 

Node.js as a Web Server - add web header

The HTTP module can create an HTTP server that listens to server ports and gives a response back to the client. Use the createServer() method to create an HTTP server:

var http = require('http');

//create a server object:
http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/html'});
  res.write('Hello World!'); //write a response to the client
  res.end(); //end the response
}).listen(8080); //the server object listens on port 8080 

Using fs (file system module) - Read from a file - file not found

// use fs, the file system module
const fs = require('fs')
fs.readFile('./starter2.txt', 'utf8', (err,data) =>{
console.log(data);
})
output
undefined

Using fs (file system module) - Read from a file - file not found and print error

// use fs, the file system module
const fs = require('fs')
fs.readFile('./starter2.txt', 'utf8', (err,data) => {
    //if error is found, show error
    if (err) throw err;
    // print content
    console.log(data);
})
output
    if (err) throw err;
             ^

[Error: ENOENT: no such file or directory, open 'C:\data\node\starter2.txt'] {
  errno: -4058,
  code: 'ENOENT',
  syscall: 'open',
  path: 'C:\\data\\node\\starter2.txt'
}

Using fs (file system module) - Read from a file - file not found catch with process.on

// use fs, the file system module
const fs = require('fs')
fs.readFile('./starter2.txt', 'utf8', (err,data) => {
    // throw error
    if (err) throw err;
    // print content
    console.log(data);
})
// Hello will probably show up on console first because fs.readFile is synchronous
console.log("Hello");

// Exit on uncaught error
// The process object in Node.js is a global object that can be accessed inside any module without requiring it.
process.on('uncaughtException', err => {
    console.error(`There was uncaught error: ${err}`)
    process.exit(1)
})

output
There was uncaught error: Error: ENOENT: no such file or directory, open 'C:\data\node\starter2.txt'

Using fs (file system module) - Read from a file - use path module

const fs = require('fs')
// use path module to ensure agnostic path (linux vs windows)
const path=require('path')

fs.readFile(path.join(__dirname, '','starter.txt'), 'utf8', (err, data) =>{
    // throw error
    if (err) throw err;
    // print content
    console.log(data);
})
console.log("Hello");

Using fs (file system module) - Write to file

const fs = require('fs')
const path=require('path')

data = "123"
// Write to file
fs.writeFile(path.join(__dirname, '','reply.txt'), data, (err) => { 
	if (err) throw err;
	console.log('Write Complete')
	}
)
console.log("Hello");

Using fs (file system module) - Append to file

const fs = require('fs')
const path=require('path')

data = "123"
// Append to file
fs.AppendFile(path.join(__dirname, '','reply.txt'), data, (err) => { 
	if (err) throw err;
	console.log('Write Complete')
	}
)
console.log("Hello");

Using fs (file system module) - Append to delete file

const fs = require('fs')
const path=require('path')

// Delete file
fs.unlink(path.join(__dirname, '','reply.txt'), (err) => { 
	if (err) throw err;
	console.log('Deletion Complete')
	}
)

Synchronous vs Asynchronous methods


let fs = require('fs');

// write to file asynchronously and write to log using callback
// write to log may be delayed
fs.writeFile('out.txt', 'This should get written asynchronously', (err) =>{
  console.log('callback in asynchronous writeFile');
});

// with writeFileSync execution synchronous
// program will be paused untill the process is finished. 
fs.writeFileSync('out.txt', 'This should get written to file');
  console.log('called after writeFileSync ');


console.log('Last log statement of program');

output:


called after writeFileSync 
Last log statement of program     
callback in asynchronous writeFile


Async programing: read, write, delete, append

// async programing: read, write, delete, append  

// The async keyword, which you put in front of a function declaration to turn it into an async function. 
// An async function is a function that knows how to expect the possibility of the await keyword being 
// used to invoke asynchronous code.

// The advantage of an async function only becomes apparent when you combine it with the await keyword. 
// await only works inside async functions within regular JavaScript code, however it can be used on its 
// own with JavaScript modules.

// promises: A promise is commonly defined as a proxy for a value that will eventually become available.
// Promises are one way to deal with asynchronous code, without getting stuck in callback hell.

const fsPromises = require('fs').promises
const path = require('path')

const fileOps = async () => {
    try {
        // read starter.txt file and put data to field data
        const data = await fsPromises.readFile(path.join(__dirname, 'files', 'starter.txt' ), 'utf8')
        console.log(data)
        // after getting data, unlink (delete file)
        await fsPromises.unlink(path.join(__dirname, 'files', 'starter.txt'))
        // write data to new file promiseWrite.txt
        await fsPromises.writeFile(path.join(__dirname, 'files', 'promiseWrite.txt'), data)
        // append to file 
        await fsPromises.appendFile(path.join(__dirname, 'files', 'promiseWrite.txt'), '\n\nNice to meet you!'),   
        // rename file
        await fsPromises.rename(path.join(__dirname, 'files', 'promiseWrite.txt'), path.join(__dirname, 'files', 'promiseComplete.txt'))
        // read promiseComplete.txt file and put data to field data
        const newData = await fsPromises.readFile(path.join(__dirname, 'files', 'promiseComplete.txt' ), 'utf8')
        console.log(newData)

    } catch (err) {
        console.error(err);
    }
}

fileOps();

Inefficient use of node server - blocks server for 5 seconds

// inefficient use of node server - blocks processing for 5 seconds
// got to  http://localhost:8080/

const express = require('express')
const app = express()
const port = 8080

function doWork(duration) {
  const start = Date.now();  
  while (Date.now() - start < duration) { 
  // do nothing but delay 5 seconds  
   }
}

app.get('/', (req,res) => {
  // handled in event loop for 5 seconds; event loop can do noting else
  doWork(5000);
  res.send('Hi there');
});

app.listen(port);



More efficient use of node server

// more efficient use of node server - blocks server for 5 seconds
// Using cluster we can make sure fast page does not have to wait in line behind slow page to process
// http://localhost:8080/fast
// http://localhost:8080/slow

// Cluster manager monitors heath of each instance.  First instance run is Cluster Manager
// Cluster Manager then starts up Worker Instances.  Worker Instances process incoming requests
// Cluster manager uses cluster module from node standard library
// Function called fork(): node goes back to js file and executes request again. 
// First time creates Cluster manager, subsequent times, creates worker instances.

const cluster = require('cluster');

// Is file executed in master mode?
if (cluster.isMaster){
  // causes index.js to be executed again in child mode
  // create two servers to improve results. We can add more servers, but at a certain point we will get start getting diminishing returns
  cluster.fork();
  cluster.fork();

}
else{
  // child mode: act like server and do nothing else
  const express = require('express');
  const app = express();
  const port = 8080;
  function doWork(duration) {
    const start = Date.now();  
    while (Date.now() - start < duration) { 
    // do nothing but delay 5 seconds  
     }
  }
  app.get('/slow', (req,res) => {
    // handled in event loop for 5 seconds; event loop can do noting else
    doWork(5000);
    res.send('Still slower');
  });
  
  app.get('/fast', (req,res) => {    
    res.send('Now we are getting faster');
  });
  app.listen(port);
}

createReadStream and createWriteStream


// The function fs.createReadStream() allows you to open up a readable stream in a 
// very simple manner. All you have to do is pass the path of the file to start 
// streaming in. It turns out that the response (as well as the request) objects 
// are streams.

// The function fs.createWriteStream() creates a writable stream in a very simple manner. 
// After a call to fs.createWriteStream() with the filepath, you have a writeable stream 
// to work with. It turns out that the response (as well as the request) objects are streams. 


const fs = require('fs')

const rs = fs.createReadStream('./files/lorem.txt' , {encoding: 'utf8'})
const ws = fs.createWriteStream('./files/new-lorem.txt' )
rs.on('data', (dataChunk) =>  {
    ws.write(dataChunk)
})


Using NPM

npm is the package manager for the Node JavaScript platform. It puts modules in place so that node can find them, and manages dependency conflicts intelligently. It is extremely configurable to support a wide variety of use cases. Most commonly, it is used to publish, discover, install, and develop node programs.

Nodemon is a tool that helps develop node.js based applications by automatically restarting the node application when file changes in the directory are detected.

date-fns is a date utility library that provides a comprehensive toolset for manipulating JavaScript dates in a browser & Node. It provides over 140 functions for comparing, manipulating, and formatting dates and timestamps.

  • add npm package for project, command: npm init and accept all default
  • install nodemon globally: npm i nodemon
  • try the nodemon command
  • in Windows powershell Set-ExecutionPolicy RemoteSigned -Scope CurrentUser
  • add data function package npm i date-fns
  • open package.json file

running command with nodemon

PS C:\data\node\NewFolder> nodemon index
[nodemon] 2.0.15
[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): *.*
[nodemon] watching extensions: js,mjs,json
[nodemon] starting `node index index.js`
testing
[nodemon] clean exit - waiting for changes before restart

Contents of package.json. Note the entry for dependencies

{
  "name": "newfolder",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "date-fns": "^2.28.0"
  }
}

Using date-fns

date-fns is a date utility library that provides a comprehensive toolset for manipulating JavaScript dates in a browser & Node. It provides over 140 functions for comparing, manipulating, and formatting dates and timestamps.

const {format} = require('date-fns')
console.log(format(new Date(), 'yyy-MM-dd\tHH:mm:ss'))
output:
2022-01-01      16:00:40

UUID

The uuid, or universally unique identifier, npm package is a secure way to generate cryptographically strong unique identifiers with Node.js that doesn't require a large amount of code.

Install uuid
npm i uuid
Using uuid
const {format} = require('date-fns')
const {v4: uuid} = require('uuid')

console.log(format(new Date(),'yyy-MM-dd\tHH:mm:ss'))
console.log(uuid()) 
output:
2022-01-01      16:25:29
88173750-a2d5-4602-9222-bbda58137a29

Is node js multi-threaded?

// Show that Node.js is single-threaded but in the background it uses 
// multiple threads to execute asynchronous code 

const crypto = require('crypto');

function myCryptoFunction(x) {
  var start = Date.now();
  for (let step = 0; step < x; step++) {
    crypto.pbkdf2('a', 'b', 10000, 512, 'sha512', () => {
      // how many miniseconds does it take to generate hash
      console.log( (Date.now() - start));
    });
  }
}

// run once
setTimeout(myCryptoFunction, 8000, 1);

// when we run twice, we would expect it to take twice the time
// actually takes only 10-15% more time
// demonstrates that in the background node.js uses multiple 
// threads to execute asynchronous code 
setTimeout(myCryptoFunction, 8000, 2 );

output:

134
156
152

Is node js multi-threaded?


// thread.js
// some functions in libuv library may use external thread pool for "expensive" calculations
// this example demonstrate that that crypto.pbkdf2 is multi-threaded
// the two functions below complete at almost same time.

const crypto = require('crypto')
const start = Date.now();

// call crypto pbkdf2 function
    crypto.pbkdf2('a', 'b', 100000, 512, 'sha512', ()=>{
// benchmark  program in milliseconds
      console.log('1:' , Date.now() - start );
} );

// repeat 
crypto.pbkdf2('a', 'b', 100000, 512, 'sha512', ()=>{
    // benchmark  program in milliseconds
          console.log('2:' , Date.now() - start );
    } );

demonstrates libuv and OS Async Helpers


// pick up google home page
// demonstrates libuv and OS Async Helpers
// libuv delegates work to underlying operating system which decides how to use threads
// libuv is a multi-platform C library that provides support for asynchronous 
// I/O based on event loops. It is primarily designed for use in Node.js but 
// it is also used by other software projects.
// “OS Async Helpers” are used when any low-level OS operations take place.

const OS = require('os');

// show number of logical cores your machine is running. 
console.log('cores=' , OS.cpus().length);

// set threadpool to number of logical cores
process.env.UV_THREADPOOL_SIZE = OS.cpus().length;

const https = require('https');
const crypto = require('crypto')
const fs = require('fs');
const start = Date.now();

// https requests uses underlying operating system
function getPage() {
  https.request('https://www.google.com' , res => {
      res.on('data', () => {} );
      res.on('end', () => {
      console.log('Task 1:' , Date.now() - start) ;
   });
 })
 .end();
}

// 
function doHash() {
    crypto.pbkdf2('a', 'b', 100000, 512, 'sha512', ()=>{
    console.log('Task 3: Hash' , Date.now() - start );
  });
}

// 1. Get web page 
getPage();

// 2. read this file
// fs module does not work wit thread pool. Disk file reads usually takes a long time
fs.readFile('multitask.js' , 'utf8' , () =>{
  console.log( 'Task 2. Read file:', Date.now() - start);
});


// 3. calculate hash 5 times
for (let i = 0; i < 5; i++) {
  doHash();
}

output:
 output:
 Task 1: 387
 Task 3: Hash 1546
 Task 3: Hash 1561
 Task 3: Hash 1570
 Task 2. Read file: 1571
 Task 3: Hash 1596
 Task 3: Hash 2503

Create a LogEvent Module

// module name index.js
// uses module logEvents

const logEvents = require('./logEvents')
const EventEmitter = require('events')
class MyEmitter extends EventEmitter{}

//initialize object 
const myEmitter = new MyEmitter();

// add listner for log events 
 myEmitter.on('log', (msg) => logEvents(msg))

setTimeout(()  => {
     //emit event 
     myEmitter.emit('log', 'Log event emitted');
 }
)

module name logEvents.js

module function: write to log file eventlog.txt

// module name logEvents.js
// module function: write to log file eventlog.txt
const {format} = require('date-fns')
const {v4: uuid} = require('uuid')
const  fs = require('fs')
const  fsPromises = require('fs').promises
const path = require('path')
 
const logEvents = async (message) => {
    const dateTime = `${format(new Date(),'yyy-MM-dd\tHH:mm:ss')}`        
    const logItem =  `${dateTime}\t${uuid()}\t${message}\n`        
    // to test:
    //console.log(logItem)
    try {
        if (!fs.existsSync(path.join(__dirname, 'logs'))) { 
        }
        await fsPromises.appendFile(path.join(__dirname, 'logs' , 'eventlog.txt'), logItem)
    } catch (err) {
        console.log(err);
    }
}
module.exports = logEvents 

Create a simple web server


// create a web server
// use browser link: http://localhost:3500/
// single response to anything that comes to port 3500
// returns  json object 

const http = require('http');
const port = 3500;

const server = http.createServer(function(req,res){
	res.setHeader('Content-type', 'application/json')
	res.setHeader('Access-Control-Allow','*')
	res.writeHead(200) // status OK = 20
	let dataObj = {"id":123, "name":"Bob", "email":"bob@work.org"};
    let data = JSON.stringify(dataObj);
    res.end(data);
  });


server.listen(port, function(error){
	if (error) {
		 console.log('Something went wrong',error)
	}
	else {
		console.log('Server is listening on port ' + port)
	}
	 
});

Create a web server and server home page and REST API


// Create a web server and server home page and REST API

const http = require('http');
const path = require('path');
const fs = require('fs');
const PORT =  3500;

// example of home page
// make sure to add page called  /public/index.html
// use: http://localhost:3500/ 

const server = http.createServer((req, res) => {
	if (req.url === '/'){
		fs.readFile(
			path.join(__dirname, 'public' , 'index.html'),
			(err,content) => {
				if(err) throw err;
				res.writeHead(200, {'Content-Type': 'text/html' });
				res.end(content);
				}
			);
        }

// example of API Rest interface
// use: http://localhost:3500/api/users
	if (req.url === '/api/users'){
		const users = [
		{name: 'Bob Smith', age: '40'} ,
		{name: 'John Doe', age: '30'}
		];
			res.writeHead(200,{'Content-Type': 'application/json' });
			
			res.end(JSON.stringify(users));
	};
});

server.listen(PORT, function(error){
    if (error) {
        console.log('Something went wrong',error)
    }
    else {
        console.log('Server is listening on port ' +PORT)
    }
});

Using node with Express JS

// Express.js, or simply Express, is a back end web application framework for Node.js
// It is designed for building web applications and APIs. It has been called the 
// de facto standard server framework for Node.js.





Node and MongoDB: connecting to database, Creating one or Multiple Records

// install drivers:
// npm install mongodb
// npm list mongodb
// mongodb@4.4.1

// mongo stores data in BSON (JSON document format) in collections (like tables)
// every document contains value of "_id" 
// tutorial reference: https://www.youtube.com/watch?v=fbYExfeFsI0&t=1161s

// connection screen:
// mongodb+srv://admin:@cluster0.erecw.mongodb.net/myFirstDatabase?retryWrites=true&w=majority
// user: admin password: password123#
// add IP address to whitelist!

const {CongoClient, MongoClient}  = require('mongodb')

async function main() {
    const uri = "mongodb+srv://admin:password123%23@cluster0.erecw.mongodb.net/myFirstDatabase?retryWrites=true&w=majority"
    const client = new MongoClient(uri);
    try
    {
        await client.connect();        
        console.log('connected\n');        
        await listDatabases(client);
        // create new record 
        await createListing(client, {
            name: "Lovely Loft",
            summary: "A charming loft in Paris",
            bedrooms: 1,
            bathrooms: 1
            })
        
        // create multiple records
        await createMultipleListing(client,newListings)

        // find one record     
        await findOneListByName(client, 'Another Lovely Loft')

    } catch(e) {
            console.error(e);
    }
        finally {
            await client.close();
            console.log('closed');
    }
}

// list all databases
async function listDatabases(client) {
    const databaseList = await client.db().admin().listDatabases();
    console.log("Databases:");
    databaseList.databases.forEach(db=>{
            console.log(`- ${db.name}`);
    })
}

// Create a new document (Air BnB Listing)
async function createListing(client,newListing) {
	const result = await client.db("sample_airbnb").collection("listingsAndReviews")
	.insertOne(newListing);
	console.log(`New listing created with the following id: ${result.insertedId}`);
}				

let newListings = 
[
	{
	name: "Lovely Loft",
	summary: "A charming loft in Paris",
	bedrooms: 1,
	bathrooms: 1
	},
	{
	name: "Another Lovely Loft",
	summary: "A really charming loft in Paris",
	bedrooms: 2,
	bathrooms: 1
	}		
];

// Find specific listing (finds first on only)  -> not working -> never finds record
async function findOneListByName(client, nameOfListing){
	const result = await client.db("sample_airbnb").collection("ListingsAndReviews").findOne({name:nameOfListing});	    
	if (result){
        console.log(`Found a listing in the collection with the name '${nameOfListing}'`);
        console.log(result);
    }
    else{        
        console.log(`No listings found with the name '${nameOfListing}'`);	
		}
}

main().catch(console.error);


Node and MongoDB: find multiple documents

// tutorial reference: https://www.youtube.com/watch?v=fbYExfeFsI0&t=1161s
// https://www.mongodb.com/developer/quickstart/node-crud-tutorial/


// mongodb+srv://admin:@cluster0.erecw.mongodb.net/myFirstDatabase?retryWrites=true&w=majority
// user: admin password: password123#
// add IP address to whitelist!

const {CongoClient, MongoClient}  = require('mongodb')

async function main() {
    const uri = "mongodb+srv://admin:password123%23@cluster0.erecw.mongodb.net/myFirstDatabase?retryWrites=true&w=majority"
    const client = new MongoClient(uri);
    try
    {
        await client.connect();        
        console.log('connected\n');        

        // find Listings With Minimum Bedrooms, Bathrooms and most Recent Reviews
        await findListingsWithMinimumBedroomsBathroomsAndMostRecentReviews(client, {
            minimumNumberOfBedrooms: 4,        
            minimumNumberOfBathrooms: 2,        
            maximumNumberOfResults: 5        
        });
        

    } catch(e) {
            console.error(e);
    }
        finally {
            await client.close();
            console.log('closed');
    }
}

 // find Listings With Minimum Bedrooms, Bathrooms and most Recent Reviews
 // set defaulst to zero
async function findListingsWithMinimumBedroomsBathroomsAndMostRecentReviews(client, {
    minimumNumberOfBedrooms = 0,
    minimumNumberOfBathrooms = 0,
    maximumNumberOfResults = Number.MAX_SAFE_INTEGER
} = {}) {
    // returns cursor which allows us to traverse results
    // use find to find multiple
    // $gte means "greater than or equal to" 
    // sort in descending order (-1)
    // limit number of records in cursor
	// retreive contents of cursor into array name "result"
    const cursor = client.db("sample_airbnb").collection("listingsAndReviews").find(
                            {
                                bedrooms: { $gte: minimumNumberOfBedrooms },
                                bathrooms: { $gte: minimumNumberOfBathrooms }
                            }
                            ).sort({ last_review: -1 })
                            .limit(maximumNumberOfResults);

    // put results in array callled results using toArray function
    const results = await cursor.toArray();

    // process and print results to console
    if (results.length > 0) {
        console.log(`Found listing(s) with at least ${minimumNumberOfBedrooms} bedrooms and ${minimumNumberOfBathrooms} bathrooms:`);
        results.forEach((result, i) => {
            date = new Date(result.last_review).toDateString();

            console.log();
            console.log(`${i + 1}. name: ${result.name}`);
            console.log(`   _id: ${result._id}`);
            console.log(`   bedrooms: ${result.bedrooms}`);
            console.log(`   bathrooms: ${result.bathrooms}`);
            console.log(`   most recent review date: ${new Date(result.last_review).toDateString()}`);
        });
    } else {
        console.log(`No listings found with at least ${minimumNumberOfBedrooms} bedrooms and ${minimumNumberOfBathrooms} bathrooms`);
    }
}

main().catch(console.error);

output:

 
 Found listing(s) with at least 4 bedrooms and 2 bathrooms:
 
 1. name: Spectacular Modern Uptown Duplex
    _id: 582364
    bedrooms: 4
    bathrooms: 2.5
    most recent review date: Wed Mar 06 2019
 ...

Node and MongoDB: Updating a single Document

 

// set up database at https://cloud.mongodb.com/
// The updateOne() method allows you to update a single document that satisfies a condition.
   // The filter is a document that specifies the criteria for the update. 
   // If the filter matches multiple documents, then the updateOne() method updates only the first document. 
   // If you pass an empty document {} into the method, it will update the first document returned in the collection.
   // The update is a document that specifies the change to apply.
   // The options argument provides some options for updates that won’t be covered in this tutorial.
   // The updateOne() method returns a document that contains some fields. The notable ones are:
      // The matchedCount returns the number of matched documents.
      // The modifiedCount returns the number of updated documents. In the case of the updateOne() method, 
      // it can be either 0 or 1.
// don't forget to add IP address to whitelist!

const {CongoClient, MongoClient}  = require('mongodb')

async function main() {
    const uri = "mongodb+srv://admin:password123%23@cluster0.erecw.mongodb.net/myFirstDatabase?retryWrites=true&w=majority"
    const client = new MongoClient(uri);
    try
    {
        await client.connect();        
        console.log('connected\n');        

        // update specific listing by name, filter on string "Fern Forest Getaway - entire house"
        await upDateListingByName(client, "Fern Forest Getaway - entire house", {bedrooms:2, beds:1});
        
    } catch(e) {
            console.error(e);
    }
        finally {
            await client.close();
            console.log('closed');
    }
}

// updating first document that matches query
 // 

 async function upDateListingByName(client, nameOfListing,updatedListing)
 {
    const result = await client.db("sample_airbnb").collection("listingsAndReviews").updateOne( 
        {name:nameOfListing} , {$set:updatedListing} );
        console.log(result);
    console.log(`${result.matchedCount} documents(s) matched the query criteria`);
    console.log(`${result.modifiedCount} documents(s) was/were updated`);
 }

 main().catch(console.error);
 async function updateListingByName(client, nameOfListing, updatedListing) {
    const result = await client.db("sample_airbnb").collection("listingsAndReviews")
                        .updateOne({ name: nameOfListing }, { $set: updatedListing });
    console.log(`${result.matchedCount} document(s) matched the query criteria.`);
    console.log(`${result.modifiedCount} document(s) was/were updated.`);
}

// output:
// connected
// 
// {
//   acknowledged: true,
//   modifiedCount: 1,
//   upsertedId: null,
//   upsertedCount: 0,
//  matchedCount: 1
// }
// 1 documents(s) matched the query criteria
// 1 documents(s) was/were updated
// closed


Node and MySql


// npm install --save mysql 
// npm install --save express

const express = require('express');
const mysql = require('mysql');
const portnumber = 3500;
const app = express();

// const connection 
const db = mysql.createConnection({
    host: 'localhost',
    user: 'root',
    password: '',
    database: 'world',
    database: 'nodemysql',
});

// Connect 
db.connect((err) => {
    if(err){
        throw err;
    }
    console.log('Mysql connected');    
});

app.listen(portnumber, () =>  {
    console.log('Server started on port 3000')
})

// Create database 
app.get('/createdb', (req,res) => {
    let sql = 'CREATE DATABASE nodemysql';    
    db.query(sql, (err, result ) => {
        if(err) throw err;
        console.log(result);
        res.send('Database created');
    });
});

// Create database 
app.get('/creatpoststable', (req,res) => {
    let sql = 'CREATE TABLE posts (id int  AUTO_INCREMENT, title VARCHAR(255), body VARCHAR(255), PRIMARY KEY (id));';    
    db.query(sql, (err, result ) => {
        if(err) throw err;
        console.log(result);
        res.send('Database created');
    });
});

// Add post 1
app.get('/addpost1', (req,res) => {
    let post = {title: 'Post One' , body: 'This is post one'};
	let sql = 'INSERT into posts set ?';
    let query = db.query(sql, post, (err, result ) => {
        if(err) throw err;
        console.log(result);
        res.send('Post 1 created');
    });
});

// Get posts 
app.get('/getposts', (req,res) => {    
	let sql = 'SELECT * FROM posts';
    let query = db.query (sql, (err, results ) => {
        if(err) throw err;
        console.log(results);
        res.send('Posts fetched...');
    });
});


// Select single post
// http://localhost:3500/getepost/2
app.get('/getpost/:id', (req, res) => {
    let sql = `SELECT * FROM posts WHERE id = ${req.params.id}`;
    let query = db.query(sql, (err, result) => {
        if(err) throw err;
        console.log(result);
        res.send('Post fetched...');
    });
});

// Select single post
// http://localhost:3500/updatepost/2
app.get('/updatepost/:id', (req, res) => {
    let newTitle = 'Updated title'
    let sql = `UPDATE posts SET title = '${newTitle}' WHERE id = ${req.params.id}`;
    let query = db.query(sql, (err, result) => {
        if(err) throw err;
        console.log(result);
        res.send('Post updated...');
    });
});



// Delete single post
// http://localhost:3500/deletepost/2
app.get('/deletepost/:id', (req, res) => {
    let newTitle = 'Updated title'
    let sql = `DELETE from posts WHERE id = ${req.params.id}`;
    let query = db.query(sql, (err, result) => {
        if(err) throw err;
        console.log(result);
        res.send('Post deleted...');
    });
});