diff --git a/.gitignore b/.gitignore
index 2f49144f0..708374c22 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,6 @@
node_modules/
+/*/.env
+*/node_modules
*/node_modules/
**/*.DS_Store
**/*-secret.json
diff --git a/Week1/.gitignore b/Week1/.gitignore
index 7df420767..b756fed36 100644
--- a/Week1/.gitignore
+++ b/Week1/.gitignore
@@ -1,3 +1,6 @@
package.json
package-lock.json
-create-table.js
\ No newline at end of file
+create-table.js
+
+
+Week1/node_modules/
\ No newline at end of file
diff --git a/Week1/exercise_1.js b/Week1/exercise_1.js
new file mode 100644
index 000000000..965a3ca5d
--- /dev/null
+++ b/Week1/exercise_1.js
@@ -0,0 +1,76 @@
+const mysql = require('mysql');
+
+const connection = mysql.createConnection({
+ host: 'localhost',
+ user: 'hyfuser',
+ password: 'hyfpassword',
+ multipleStatements: true
+});
+
+
+/*Connect to SQL server*/
+connection.connect(err => {
+ if (err) {
+ return console.error('Connection error: ' + err.stack);
+ }
+ console.log('Connected!');
+});
+
+
+/*SQL queries*/
+const createDatabaseAndTables =
+ `DROP DATABASE IF EXISTS meetup;
+ CREATE DATABASE meetup;
+ USE meetup;
+
+ CREATE TABLE Invitee (
+ invitee_no INT AUTO_INCREMENT PRIMARY KEY,
+ invitee_name VARCHAR(100),
+ invited_by VARCHAR(100)
+ );
+
+ CREATE TABLE Room (
+ room_no INT AUTO_INCREMENT PRIMARY KEY,
+ room_name VARCHAR(50),
+ floor_number INT
+ );
+
+ CREATE TABLE Meeting (
+ meeting_no INT AUTO_INCREMENT PRIMARY KEY,
+ meeting_title VARCHAR(100),
+ starting_time DATETIME,
+ ending_time DATETIME,
+ room_no INT,
+ FOREIGN KEY (room_no) REFERENCES Room(room_no)
+ );
+
+ INSERT INTO Room (room_name, floor_number) VALUES
+ ('Paris', 1),
+ ('New York', 2),
+ ('Tokyo', 3),
+ ('London', 4),
+ ('Berlin', 5);
+
+ INSERT INTO Invitee (invitee_name, invited_by) VALUES
+ ('Victor Hugo', 'Alexandre Dumas'),
+ ('Mark Twain', 'Henry James'),
+ ('Haruki Murakami', 'Kenzaburo Oe'),
+ ('Charles Dickens', 'Wilkie Collins'),
+ ('Albert Einstein', 'Niels Bohr');
+
+ INSERT INTO Meeting (meeting_title, starting_time, ending_time, room_no) VALUES
+ ('Literary Classics Discussion', '2024-08-01 09:00:00', '2024-08-01 10:00:00', 1),
+ ('American Literature Seminar', '2024-08-02 11:00:00', '2024-08-02 12:00:00', 2),
+ ('Japanese Fiction Workshop', '2024-08-03 14:00:00', '2024-08-03 15:00:00', 3),
+ ('Victorian Literature Symposium', '2024-08-04 16:00:00', '2024-08-04 17:00:00', 4),
+ ('Scientific Innovations Forum', '2024-08-05 13:00:00', '2024-08-05 14:00:00', 5);`;
+
+
+// Execute the queries
+connection.query(createDatabaseAndTables, (error, results, fields) => {
+ if (error) throw error;
+ console.log('Database and tables created, and data inserted');
+});
+
+// Close the connection
+connection.end();
\ No newline at end of file
diff --git a/Week1/exercise_2.js b/Week1/exercise_2.js
new file mode 100644
index 000000000..f4b24fecf
--- /dev/null
+++ b/Week1/exercise_2.js
@@ -0,0 +1,44 @@
+const mysql = require('mysql');
+
+const connection = mysql.createConnection({
+ host: 'localhost',
+ user: 'hyfuser',
+ password: 'hyfpassword',
+ database: 'world'
+});
+
+/*Connect to SQL server*/
+connection.connect(err => {
+ if (err) {
+ return console.error('Connection error: ' + err.stack);
+ }
+ console.log('Connected!');
+});
+
+
+// Queries
+const queries = [
+ "SELECT Name FROM country WHERE Population > 8000000;",
+ "SELECT Name FROM country WHERE Name LIKE '%land%';",
+ "SELECT Name FROM city WHERE Population BETWEEN 500000 AND 1000000;",
+ "SELECT Name FROM country WHERE Continent = 'Europe';",
+ "SELECT Name FROM country ORDER BY SurfaceArea DESC;",
+ "SELECT Name FROM city WHERE CountryCode = 'NLD';",
+ "SELECT Population FROM city WHERE Name = 'Rotterdam';",
+ "SELECT Name FROM country ORDER BY SurfaceArea DESC LIMIT 10;",
+ "SELECT Name FROM city ORDER BY Population DESC LIMIT 10;",
+ "SELECT SUM(Population) AS WorldPopulation FROM country;"
+];
+
+
+// Execute each query
+queries.forEach((query, index) => {
+ connection.query(query, (error, results) => {
+ if (error) throw error;
+ console.log(`Query ${index + 1}:`);
+ console.log(results);
+ });
+});
+
+// End the connection
+connection.end();
\ No newline at end of file
diff --git a/Week2/connection_query.js b/Week2/connection_query.js
new file mode 100644
index 000000000..60e0cdc7b
--- /dev/null
+++ b/Week2/connection_query.js
@@ -0,0 +1,29 @@
+//C:\Users\knowl\Documents\hyf\databases\Week2\connection_query.js
+import mysql from 'mysql';
+
+export const createNewConnection = () => {
+ return mysql.createConnection({
+ host: 'localhost',
+ user: 'hyfuser',
+ password: 'hyfpassword',
+ multipleStatements: true,
+ });
+};
+
+export const useDatabase = (connection) => {
+ return new Promise((resolve, reject) => {
+ const createDatabaseAndUse = `
+ CREATE DATABASE IF NOT EXISTS w2_research;
+ USE w2_research;
+ `;
+ connection.query(createDatabaseAndUse, (err, results) => {
+ if (err) {
+ console.error('Error creating or selecting database:', err.stack);
+ reject(err);
+ return;
+ }
+ console.log('Database selected successfully.');
+ resolve();
+ });
+ });
+};
\ No newline at end of file
diff --git a/Week2/exercise_1.js b/Week2/exercise_1.js
new file mode 100644
index 000000000..b5f052265
--- /dev/null
+++ b/Week2/exercise_1.js
@@ -0,0 +1,99 @@
+//C:\Users\knowl\Documents\hyf\databases\Week2\exercise_1.js
+import {createNewConnection, useDatabase} from './connection_query.js';
+
+
+const createAuthorsTable = (connection) => {
+ return new Promise((resolve, reject) => {
+ const createAuthorsTableQuery = `
+ CREATE TABLE IF NOT EXISTS authors (
+ author_id INT AUTO_INCREMENT PRIMARY KEY,
+ author_name VARCHAR(100) NOT NULL,
+ university VARCHAR(100),
+ date_of_birth DATE,
+ h_index INT,
+ gender ENUM('Male', 'Female', 'Other')
+ );
+ `;
+ connection.query(createAuthorsTableQuery, (err, results) => {
+ if (err) {
+ console.error('Error creating authors table:', err.stack);
+ reject(err);
+ return;
+ }
+ console.log('Authors table created.');
+ resolve();
+ });
+ });
+};
+
+const addMentorColumn = (connection) => {
+ return new Promise((resolve, reject) => {
+ const checkColumnExistsQuery = `
+ SELECT COUNT(*) AS columnExists
+ FROM information_schema.columns
+ WHERE table_name = 'authors'
+ AND column_name = 'mentor';
+ `;
+
+ connection.query(checkColumnExistsQuery, (err, results) => {
+ if (err) {
+ console.error('Error checking for mentor column:', err.stack);
+ reject(err);
+ return;
+ }
+
+ const columnExists = results[0].columnExists;
+
+ if (columnExists) {
+ console.log('Mentor column already exists. No changes made.');
+ resolve();
+ } else {
+ const addMentorColumnQuery = `
+ ALTER TABLE authors
+ ADD COLUMN mentor INT,
+ ADD CONSTRAINT fk_mentor
+ FOREIGN KEY (mentor) REFERENCES authors(author_id)
+ ON DELETE SET NULL
+ ON UPDATE CASCADE;
+ `;
+
+ connection.query(addMentorColumnQuery, (err, results) => {
+ if (err) {
+ console.error('Error adding mentor column:', err.stack);
+ reject(err);
+ return;
+ }
+ console.log('Mentor column added with foreign key constraint.');
+ resolve();
+ });
+ }
+ });
+ });
+};
+
+
+const exerciseOne = async () => {
+ const connection = createNewConnection();
+ connection.connect(err => {
+ if (err) {
+ return console.error('Connection error: ' + err.stack);
+ }
+ console.log('exercise_1: Connected!');
+ });
+
+
+ try {
+ await useDatabase(connection) ; // Select the database
+ await createAuthorsTable(connection) ; // Create the authors table
+ await addMentorColumn(connection) ; // Add the mentor column with foreign key
+
+ } catch (err) {
+ console.error('Failed to set up the database:', err);
+ } finally {
+ connection.end();
+ }
+};
+
+
+exerciseOne();
+
diff --git a/Week2/exercise_2.js b/Week2/exercise_2.js
new file mode 100644
index 000000000..18d1168b1
--- /dev/null
+++ b/Week2/exercise_2.js
@@ -0,0 +1,202 @@
+//C:\Users\knowl\Documents\hyf\databases\Week2\exercise_2.js
+import {createNewConnection, useDatabase} from './connection_query.js';
+
+
+const createResearchPapersTable = async (connection) => {
+ const createResearchPapersTableQuery = `
+ CREATE TABLE IF NOT EXISTS research_papers (
+ paper_id INT AUTO_INCREMENT PRIMARY KEY,
+ paper_title VARCHAR(255) NOT NULL,
+ conference VARCHAR(255),
+ publish_date DATE
+ );
+ `;
+ await new Promise((resolve, reject) => {
+ connection.query(createResearchPapersTableQuery, (err, results) => {
+ if (err) {
+ console.error('Error creating research_papers table:', err.stack);
+ reject(err);
+ return;
+ }
+ console.log('Research papers table created.');
+ resolve();
+ });
+ });
+};
+
+const createAuthorPapersTable = async (connection) => {
+ const createAuthorPapersTableQuery = `
+ CREATE TABLE IF NOT EXISTS author_papers (
+ author_id INT,
+ paper_id INT,
+ PRIMARY KEY (author_id, paper_id),
+ FOREIGN KEY (author_id) REFERENCES authors(author_id)
+ ON DELETE CASCADE
+ ON UPDATE CASCADE,
+ FOREIGN KEY (paper_id) REFERENCES research_papers(paper_id)
+ ON DELETE CASCADE
+ ON UPDATE CASCADE
+ );
+ `;
+ await new Promise((resolve, reject) => {
+ connection.query(createAuthorPapersTableQuery, (err, results) => {
+ if (err) {
+ console.error('Error creating author_papers table:', err.stack);
+ reject(err);
+ return;
+ }
+ console.log('Author papers table created.');
+ resolve();
+ });
+ });
+};
+
+
+const authors = [
+ ['Alan Turing', 'University of Cambridge', '1912-06-23', 67, 'Male', null],
+ ['Ada Lovelace', 'University of London', '1815-12-10', 45, 'Female', null],
+ ['John von Neumann', 'Princeton University', '1903-12-28', 86, 'Male', null],
+ ['Grace Hopper', 'Yale University', '1906-12-09', 60, 'Female', 1],
+ ['Donald Knuth', 'Stanford University', '1938-01-10', 127, 'Male', 3],
+ ['Edsger Dijkstra', 'University of Texas', '1930-05-11', 87, 'Male', null],
+ ['Tim Berners-Lee', 'MIT', '1955-06-08', 70, 'Male', 4],
+ ['Claude Shannon', 'MIT', '1916-04-30', 80, 'Male', null],
+ ['Barbara Liskov', 'MIT', '1939-11-07', 85, 'Female', null],
+ ['John McCarthy', 'Stanford University', '1927-09-04', 75, 'Male', 3],
+ ['Marvin Minsky', 'MIT', '1927-08-09', 76, 'Male', 9],
+ ['Larry Page', 'Stanford University', '1973-03-26', 64, 'Male', 12],
+ ['Sergey Brin', 'Stanford University', '1973-08-21', 63, 'Male', 11],
+ ['Don Norman', 'UC San Diego', '1935-12-25', 55, 'Male', null],
+ ['Brenda Laurel', 'UC Santa Cruz', '1950-11-20', 40, 'Female', 13]
+];
+
+
+const papers = [
+ ['On Computable Numbers, with an Application to the Entscheidungsproblem', 'Proceedings of the London Mathematical Society', '1936-11-12'],
+ ['The Analytical Engine', 'University of London', '1842-01-01'],
+ ['Theory of Games and Economic Behavior', 'Princeton University Press', '1944-03-01'],
+ ['The First Compiler', 'Harvard University', '1952-01-01'],
+ ['The Art of Computer Programming', 'Addison-Wesley', '1968-01-01'],
+ ['A Note on Two Problems in Connexion with Graphs', 'Numerische Mathematik', '1959-01-01'],
+ ['Information Management: A Proposal', 'CERN', '1989-03-01'],
+ ['A Mathematical Theory of Communication', 'Bell System Technical Journal', '1948-07-01'],
+ ['A Design Methodology for Reliable Software Systems', 'MIT', '1972-01-01'],
+ ['LISP: A Programming Language for Artificial Intelligence', 'Communications of the ACM', '1960-01-01'],
+ ['Steps Toward Artificial Intelligence', 'Proceedings of the IRE', '1961-01-01'],
+ ['The PageRank Citation Ranking: Bringing Order to the Web', 'Stanford University', '1998-01-01'],
+ ['The Anatomy of a Large-Scale Hypertextual Web Search Engine', 'Stanford University', '1999-01-01'],
+ ['The Design of Everyday Things', 'Basic Books', '1988-01-01'],
+ ['Computers as Theatre', 'Addison-Wesley', '1991-01-01'],
+ ['Quantum Mechanics and Path Integrals', 'Dover Publications', '1965-01-01'],
+ ['Reflections on Trusting Trust', 'Communications of the ACM', '1984-01-01'],
+ ['The Complexity of Theorem-Proving Procedures', 'ACM Symposium on Theory of Computing', '1971-01-01'],
+ ['Sketchpad: A Man-Machine Graphical Communication System', 'Spring Joint Computer Conference', '1963-01-01'],
+ ['No Silver Bullet: Essence and Accidents of Software Engineering', 'IFIP Congress', '1986-01-01'],
+ ['Introduction to Automata Theory, Languages, and Computation', 'Addison-Wesley', '1979-01-01'],
+ ['The Conceptual Framework of Computing', 'MIT', '1973-01-01'],
+ ['Design Patterns: Elements of Reusable Object-Oriented Software', 'Addison-Wesley', '1994-01-01'],
+ ['Computing Machinery and Intelligence', 'Mind', '1950-01-01'],
+ ['The CRISP-DM Process Model', 'IBM Research', '1999-01-01'],
+ ['As We May Think', 'The Atlantic', '1945-01-01'],
+ ['The Feynman Lectures on Physics', 'Addison-Wesley', '1964-01-01'],
+ ['The Mathematical Theory of Computation', 'Prentice Hall', '1972-01-01'],
+ ['The Structure of Scientific Revolutions', 'University of Chicago Press', '1962-01-01'],
+ ['Patterns of Software: Tales from the Software Community', 'Oxford University Press', '1996-01-01']
+];
+
+const authorPapers = [
+ [1, 1], [2, 2], [3, 3], [4, 4], [5, 5],
+ [6, 6], [7, 7], [8, 8], [9, 9], [10, 10],
+ [11, 11], [12, 12], [13, 13], [14, 14], [15, 15],
+ [1, 16], [2, 17], [3, 18], [4, 19], [5, 20],
+ [6, 21], [7, 22], [8, 23], [9, 24], [10, 25],
+ [11, 26], [12, 27], [13, 28], [14, 29], [15, 30]
+];
+
+const insertAuthors = async (connection) => {
+ const insertAuthorQuery = `
+ INSERT INTO authors (author_name, university, date_of_birth, h_index, gender, mentor)
+ VALUES ?
+ `;
+ await new Promise((resolve, reject) => {
+ connection.query(insertAuthorQuery, [authors], (err, results) => {
+ if (err) {
+ console.error('Error inserting authors:', err.stack);
+ reject(err);
+ return;
+ }
+ console.log('Authors inserted.');
+ resolve();
+ });
+ });
+};
+
+const insertResearchPapers = async (connection) => {
+ const insertPaperQuery = `
+ INSERT INTO research_papers (paper_title, conference, publish_date)
+ VALUES ?
+ `;
+ await new Promise((resolve, reject) => {
+ connection.query(insertPaperQuery, [papers], (err, results) => {
+ if (err) {
+ console.error('Error inserting research papers:', err.stack);
+ reject(err);
+ return;
+ }
+ console.log('Research papers inserted.');
+ resolve();
+ });
+ });
+};
+
+// Insert data into author_papers junction table
+const linkAuthorsToPapers = async (connection) => {
+ const insertAuthorPapersQuery = `
+ INSERT INTO author_papers (author_id, paper_id)
+ VALUES ?
+ `;
+ await new Promise((resolve, reject) => {
+ connection.query(insertAuthorPapersQuery, [authorPapers], (err, results) => {
+ if (err) {
+ console.error('Error inserting author_papers:', err.stack);
+ reject(err);
+ return;
+ }
+ console.log('Author papers relationships inserted.');
+ resolve();
+ });
+ });
+};
+
+
+
+const exerciseTwo = async () => {
+
+ const connection = createNewConnection();
+
+ connection.connect(err => {
+ if (err) {
+ return console.error('Connection error: ' + err.stack);
+ }
+ console.log('exercise_2: Connected!');
+ });
+
+ try {
+ await useDatabase(connection) ; // Ensure the database is selected
+ await createResearchPapersTable(connection) ; // Create the research_papers table
+ await createAuthorPapersTable(connection) ; // Create the author_papers table
+ await insertAuthors(connection) ; // Insert authors into the authors table
+ await insertResearchPapers(connection) ; // Insert research papers
+ await linkAuthorsToPapers(connection) ; // Insert author-paper relationships
+
+ console.log('Exercise steps completed.');
+ } catch (err) {
+ console.error('Failed to set up the database:', err);
+ } finally {
+ connection.end();
+ };
+ };
+
+
+
+exerciseTwo();
\ No newline at end of file
diff --git a/Week2/exercise_3.js b/Week2/exercise_3.js
new file mode 100644
index 000000000..e465a7b35
--- /dev/null
+++ b/Week2/exercise_3.js
@@ -0,0 +1,82 @@
+//C:\Users\knowl\Documents\hyf\databases\Week2\exercise_3.js
+import {createNewConnection, useDatabase} from './connection_query.js';
+
+const connection = createNewConnection();
+
+const getAuthorsAndMentors = (connection) => {
+ return new Promise((resolve, reject) => {
+ const query = `
+ SELECT
+ a1.author_name AS Author,
+ a2.author_name AS Mentor
+ FROM
+ authors a1
+ LEFT JOIN
+ authors a2 ON a1.mentor = a2.author_id;
+ `;
+ connection.query(query, (err, results) => {
+ if (err) {
+ console.error('Error fetching authors and mentors:', err.stack);
+ reject(err);
+ return;
+ }
+ console.log('Authors and their mentors:');
+ console.table(results);
+ resolve();
+ });
+ });
+};
+
+
+const getAuthorsAndPapers = (connection) => {
+ return new Promise((resolve, reject) => {
+ const query = `
+ SELECT
+ authors.*,
+ research_papers.paper_title
+ FROM
+ authors
+ LEFT JOIN
+ author_papers ON authors.author_id = author_papers.author_id
+ LEFT JOIN
+ research_papers ON author_papers.paper_id = research_papers.paper_id;
+ `;
+ connection.query(query, (err, results) => {
+ if (err) {
+ console.error('Error fetching authors and their papers:', err.stack);
+ reject(err);
+ return;
+ }
+ console.log('Authors and their published papers:');
+ console.table(results);
+ resolve();
+ });
+ });
+};
+
+
+const exerciseThree = async () => {
+ /*Prevents the connection from running twice*/
+// Check if connect() has already been called on this instance
+ if (!connection._connectCalled) {
+ connection.connect(err => {
+ if (err) {
+ return console.error('Connection error: ' + err.stack);
+ }
+ console.log('Connected!');
+ });
+ }
+ try {
+ await useDatabase(connection); // Ensure the database is selected
+ await getAuthorsAndMentors(connection); // Get authors and their mentors
+ await getAuthorsAndPapers(connection); // Get authors and their published papers
+ } catch (err) {
+ console.error('An error occurred:', err);
+ } finally {
+ connection.end(); // Close the connection after all operations
+ }
+};
+
+
+exerciseThree();
+
diff --git a/Week2/exercise_4.js b/Week2/exercise_4.js
new file mode 100644
index 000000000..1e8976738
--- /dev/null
+++ b/Week2/exercise_4.js
@@ -0,0 +1,186 @@
+//C:\Users\knowl\Documents\hyf\databases\Week2\exercise_4.js
+import {createNewConnection, useDatabase} from './connection_query.js';
+import path from 'path';
+
+console.log(`running the file exercise_4.js`);
+const connection = createNewConnection();
+
+const getPapersAndAuthorCount = (connection) => {
+ return new Promise((resolve, reject) => {
+ const query = `
+ SELECT
+ research_papers.paper_title,
+ COUNT(author_papers.author_id) AS author_count
+ FROM
+ research_papers
+ LEFT JOIN
+ author_papers ON research_papers.paper_id = author_papers.paper_id
+ GROUP BY
+ research_papers.paper_id;
+ `;
+ connection.query(query, (err, results) => {
+ if (err) {
+ console.error('Error fetching papers and author count:', err.stack);
+ reject(err);
+ return;
+ }
+ console.log('Research papers and number of authors:');
+ console.table(results);
+ resolve();
+ });
+ });
+};
+
+
+const getSumOfPapersByFemaleAuthors = (connection) => {
+ return new Promise((resolve, reject) => {
+ const query = `
+ SELECT
+ SUM(IF(authors.gender = 'Female', 1, 0)) AS female_author_paper_count
+ FROM
+ author_papers
+ LEFT JOIN
+ authors ON author_papers.author_id = authors.author_id;
+ `;
+ connection.query(query, (err, results) => {
+ if (err) {
+ console.error('Error fetching sum of papers by female authors:', err.stack);
+ reject(err);
+ return;
+ }
+ console.log('Sum of research papers published by all female authors:');
+ console.table(results);
+ resolve();
+ });
+ });
+};
+
+
+
+const getAverageHIndexPerUniversity = (connection) => {
+ return new Promise((resolve, reject) => {
+ const query = `
+ SELECT
+ university,
+ AVG(h_index) AS average_h_index
+ FROM
+ authors
+ GROUP BY
+ university;
+ `;
+ connection.query(query, (err, results) => {
+ if (err) {
+ console.error('Error fetching average h-index per university:', err.stack);
+ reject(err);
+ return;
+ }
+ console.log('Average h-index of all authors per university:');
+ console.table(results);
+ resolve();
+ });
+ });
+};
+
+
+const getSumOfPapersPerUniversity = (connection) => {
+ return new Promise((resolve, reject) => {
+ const query = `
+ SELECT
+ authors.university,
+ COUNT(author_papers.paper_id) AS total_papers
+ FROM
+ authors
+ LEFT JOIN
+ author_papers ON authors.author_id = author_papers.author_id
+ GROUP BY
+ authors.university;
+ `;
+ connection.query(query, (err, results) => {
+ if (err) {
+ console.error('Error fetching sum of papers per university:', err.stack);
+ reject(err);
+ return;
+ }
+ console.log('Sum of research papers of the authors per university:');
+ console.table(results);
+ resolve();
+ });
+ });
+};
+
+
+
+const getMinMaxHIndexPerUniversity = (connection) => {
+ return new Promise((resolve, reject) => {
+ const query = `
+ SELECT
+ university,
+ MIN(h_index) AS min_h_index,
+ MAX(h_index) AS max_h_index
+ FROM
+ authors
+ GROUP BY
+ university;
+ `;
+ connection.query(query, (err, results) => {
+ if (err) {
+ console.error('Error fetching min and max h-index per university:', err.stack);
+ reject(err);
+ return;
+ }
+ console.log('Minimum and maximum h-index of all authors per university:');
+ console.table(results);
+ resolve();
+ });
+ });
+};
+
+
+const exerciseFour = async (connection) => {
+ /*Prevents the connection from running twice*/
+// Check if connect() has already been called on this instance
+ console.log('Attempting to connect to the database...');
+ if (!connection._connectCalled) {
+ connection.connect(err => {
+ if (err) {
+ return console.error('Connection error: ' + err.stack);
+ }
+ console.log('Connected!');
+ });
+ } else {
+ console.log('Connection already established.');
+ }
+ try {
+ await useDatabase(connection); // Ensure the database is selected
+ await getPapersAndAuthorCount(connection) ; // Get all research papers and number of authors
+ await getSumOfPapersByFemaleAuthors(connection) ;// Get sum of research papers by female authors
+ await getAverageHIndexPerUniversity(connection) ;// Get average h-index per university
+ await getSumOfPapersPerUniversity(connection) ; // Get sum of research papers per university
+ await getMinMaxHIndexPerUniversity(connection) ; // Get min and max h-index per university
+ } catch (err) {
+ console.error('An error occurred:', err);
+ } finally {
+ connection.end(); // Close the connection after all operations
+ }
+};
+
+
+// console.log(`import.meta.url: ${import.meta.url}`);
+// console.log(`file://${process.argv[1]}`);
+// const filePath = `file://${path.resolve(process.argv[1]).replace(/\\/g, '/')}`;
+// console.log(`Normalized file path: ${filePath}`);
+
+// Only run this script if it's executed directly (not imported)~
+// ~because running the script on import causes duplicated connections
+
+/* `file://${process.argv[1]}` is used to get the full path to the script that is being executed
+* `file://${process.argv[1]}` is compared to import.meta.url to determine if the current module is the main module*/
+// if (import.meta.url === filePath) {
+// console.log('Executing exerciseFour function.');
+// exerciseFour(connection);
+// } else {
+// console.log('Condition not met, not executing exerciseFour.');
+// }
+
+
+exerciseFour(connection);
diff --git a/Week2/package-lock.json b/Week2/package-lock.json
new file mode 100644
index 000000000..0378743a1
--- /dev/null
+++ b/Week2/package-lock.json
@@ -0,0 +1,94 @@
+{
+ "name": "Week2",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "dependencies": {
+ "mysql": "^2.18.1"
+ }
+ },
+ "node_modules/bignumber.js": {
+ "version": "9.0.0",
+ "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.0.tgz",
+ "integrity": "sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A==",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/core-util-is": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
+ "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="
+ },
+ "node_modules/inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
+ },
+ "node_modules/isarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+ "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="
+ },
+ "node_modules/mysql": {
+ "version": "2.18.1",
+ "resolved": "https://registry.npmjs.org/mysql/-/mysql-2.18.1.tgz",
+ "integrity": "sha512-Bca+gk2YWmqp2Uf6k5NFEurwY/0td0cpebAucFpY/3jhrwrVGuxU2uQFCHjU19SJfje0yQvi+rVWdq78hR5lig==",
+ "dependencies": {
+ "bignumber.js": "9.0.0",
+ "readable-stream": "2.3.7",
+ "safe-buffer": "5.1.2",
+ "sqlstring": "2.3.1"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/process-nextick-args": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
+ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
+ },
+ "node_modules/readable-stream": {
+ "version": "2.3.7",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
+ "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
+ "dependencies": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ }
+ },
+ "node_modules/safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
+ },
+ "node_modules/sqlstring": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.1.tgz",
+ "integrity": "sha512-ooAzh/7dxIG5+uDik1z/Rd1vli0+38izZhGzSa34FwR7IbelPWCCKSNIl8jlL/F7ERvy8CB2jNeM1E9i9mXMAQ==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/string_decoder": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+ "dependencies": {
+ "safe-buffer": "~5.1.0"
+ }
+ },
+ "node_modules/util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
+ }
+ }
+}
diff --git a/Week2/package.json b/Week2/package.json
new file mode 100644
index 000000000..ede26e1f0
--- /dev/null
+++ b/Week2/package.json
@@ -0,0 +1,6 @@
+{
+ "type": "module",
+ "dependencies": {
+ "mysql": "^2.18.1"
+ }
+}
diff --git a/Week3/DinnerClubERD.drawio b/Week3/DinnerClubERD.drawio
new file mode 100644
index 000000000..ac1654ed1
--- /dev/null
+++ b/Week3/DinnerClubERD.drawio
@@ -0,0 +1,252 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Week3/assignment/.$DinnerClubERD.drawio.bkp b/Week3/assignment/.$DinnerClubERD.drawio.bkp
new file mode 100644
index 000000000..cca04a713
--- /dev/null
+++ b/Week3/assignment/.$DinnerClubERD.drawio.bkp
@@ -0,0 +1,132 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Week3/assignment/.$DinnerClubERD.drawio.dtmp b/Week3/assignment/.$DinnerClubERD.drawio.dtmp
new file mode 100644
index 000000000..b34d99eee
--- /dev/null
+++ b/Week3/assignment/.$DinnerClubERD.drawio.dtmp
@@ -0,0 +1,298 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Week3/assignment/DinnerClubERD.drawio b/Week3/assignment/DinnerClubERD.drawio
new file mode 100644
index 000000000..b34d99eee
--- /dev/null
+++ b/Week3/assignment/DinnerClubERD.drawio
@@ -0,0 +1,298 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Week3/assignment/connection_query.js b/Week3/assignment/connection_query.js
new file mode 100644
index 000000000..45c6bb19b
--- /dev/null
+++ b/Week3/assignment/connection_query.js
@@ -0,0 +1,30 @@
+//C:\Users\knowl\Documents\hyf\databases\Week3\assignment\connection_query.js
+import mysql from 'mysql';
+
+
+export const createNewConnection = () => {
+ return mysql.createConnection({
+ host: 'localhost',
+ user: 'hyfuser',
+ password: 'hyfpassword',
+ multipleStatements: true,
+ });
+};
+
+export const useDatabase = (connection) => {
+ return new Promise((resolve, reject) => {
+ const createDatabaseAndUse = `
+ CREATE DATABASE IF NOT EXISTS transactions;
+ USE transactions;
+ `;
+ connection.query(createDatabaseAndUse, (err, results) => {
+ if (err) {
+ console.error('Error creating or selecting database:', err.stack);
+ reject(err);
+ return;
+ }
+ console.log('Database selected successfully.');
+ resolve();
+ });
+ });
+};
\ No newline at end of file
diff --git a/Week3/assignment/exercise_1.md b/Week3/assignment/exercise_1.md
new file mode 100644
index 000000000..1ae40da44
--- /dev/null
+++ b/Week3/assignment/exercise_1.md
@@ -0,0 +1,17 @@
+## 1. What columns violate 1NF?
+- columns `food_code` and `food_description`. They contain multiple values, which violates atomic value rule of 1NF
+## 2. What entities do you recognize that could be extracted?
+- member
+- dinner
+- venue
+- food
+- dinner_food
+
+## 3. Name all the tables and columns that would make a 3NF compliant solution.
+- member
+- dinner
+- venue
+- food
+- dinner_food
+- member_dinner
+![img.png](../img.png)
\ No newline at end of file
diff --git a/Week3/assignment/exercise_3.js b/Week3/assignment/exercise_3.js
new file mode 100644
index 000000000..7398b007c
--- /dev/null
+++ b/Week3/assignment/exercise_3.js
@@ -0,0 +1,28 @@
+
+// given function:
+// function getPopulation(Country, name, code, cb) {
+// // assuming that connection to the database is established and stored as conn
+// conn.query(
+// `SELECT Population FROM ${Country} WHERE Name = '${name}' and code = '${code}'`,
+// function (err, result) {
+// if (err) cb(err);
+// if (result.length == 0) cb(new Error("Not found"));
+// cb(null, result[0].name);
+// }
+// );
+// }
+// code that would take advantage of SQL-injection:
+// getPopulation("Netherlands", "'; --", "' OR '1'='1")
+//SQL query:
+// SELECT Population FROM Country WHERE Name = ''; -- ' and code = ' OR '1'='1'
+
+//Rewritten function
+function getPopulation(Country, name, code, cb) {
+ // assuming that connection to the database is established and stored as conn
+ const query = `SELECT Population FROM ${Country} WHERE Name = ? and code = ?`;
+ conn.query(query, [name, code], function (err, result) {
+ if (err) return cb(err);
+ if (result.length == 0) return cb(new Error("Not found"));
+ cb(null, result[0].Population);
+ });
+}
diff --git a/Week3/assignment/transaction.js b/Week3/assignment/transaction.js
new file mode 100644
index 000000000..795c116e8
--- /dev/null
+++ b/Week3/assignment/transaction.js
@@ -0,0 +1,97 @@
+import {createNewConnection, useDatabase} from "./connection_query.js";
+
+const connection = createNewConnection();
+
+const transferAmount = (fromAccount, toAccount, amount) => {
+ return new Promise((resolve, reject) => {
+ connection.beginTransaction(err => {
+ if (err) return reject(err);
+
+ // Deduct amount from the source account
+ const deductAmountQuery = `
+ UPDATE account
+ SET balance = balance - ${connection.escape(amount)}
+ WHERE account_number = ${connection.escape(fromAccount)}
+ `;
+
+ connection.query(deductAmountQuery, (err, result) => {
+ if (err) {
+ return connection.rollback(() => {
+ reject(err);
+ });
+ }
+
+ // Add amount to the destination account
+ const addAmountQuery = `
+ UPDATE account
+ SET balance = balance + ${connection.escape(amount)}
+ WHERE account_number = ${connection.escape(toAccount)}
+ `;
+
+ connection.query(addAmountQuery, (err, result) => {
+ if (err) {
+ return connection.rollback(() => {
+ reject(err);
+ });
+ }
+
+ // Log the change in the account_changes table for the source account
+ const logChangeFromAccount = `
+ INSERT INTO account_changes (account_number, amount, changed_date, remark)
+ VALUES (${connection.escape(fromAccount)}, -${connection.escape(amount)}, NOW(), 'Transfer to account ${connection.escape(toAccount)}')
+ `;
+
+ connection.query(logChangeFromAccount, (err, result) => {
+ if (err) {
+ return connection.rollback(() => {
+ reject(err);
+ });
+ }
+
+ // Log the change in the account_changes table for the destination account
+ const logChangeToAccount = `
+ INSERT INTO account_changes (account_number, amount, changed_date, remark)
+ VALUES (${connection.escape(toAccount)}, ${connection.escape(amount)}, NOW(), 'Transfer from account ${connection.escape(fromAccount)}')
+ `;
+
+ connection.query(logChangeToAccount, (err, result) => {
+ if (err) {
+ return connection.rollback(() => {
+ reject(err);
+ });
+ }
+
+ // Commit the transaction if everything is successful
+ connection.commit(err => {
+ if (err) {
+ return connection.rollback(() => {
+ reject(err);
+ });
+ }
+ console.log('Transaction completed successfully.');
+ resolve();
+ });
+ });
+ });
+ });
+ });
+ });
+ });
+};
+
+
+connection.connect((err) => {
+ if (err) throw err;
+ console.log('Connected to the database.');
+
+ useDatabase(connection)
+ .then(() => {
+ return transferAmount(101, 102, 1000);
+ })
+ .catch((error) => {
+ console.error('Error during transaction:', error);
+ })
+ .finally(() => {
+ connection.end();
+ });
+});
\ No newline at end of file
diff --git a/Week3/assignment/transactions-create-tables.js b/Week3/assignment/transactions-create-tables.js
new file mode 100644
index 000000000..bf29653e4
--- /dev/null
+++ b/Week3/assignment/transactions-create-tables.js
@@ -0,0 +1,50 @@
+//C:\Users\knowl\Documents\hyf\databases\Week3\assignment\transactions-create-tables.js
+import {createNewConnection,useDatabase} from "./connection_query.js";
+
+// Schema for the tables
+const accountTable = {
+ account_number: 'INT PRIMARY KEY',
+ balance: 'DECIMAL(10, 2) NOT NULL'
+};
+
+const accountChangesTable = {
+ change_number: 'INT AUTO_INCREMENT PRIMARY KEY',
+ account_number: 'INT NOT NULL',
+ amount: 'DECIMAL(10, 2) NOT NULL',
+ changed_date: 'DATETIME NOT NULL',
+ remark: 'VARCHAR(255)'
+};
+
+
+// Function to create a table
+const createTable = (tableName, schema, foreignKeys='') => {
+ const columns = Object.entries(schema).map(([key, type]) => `${key} ${type}`).join(', ');
+ const query = `CREATE TABLE IF NOT EXISTS ${tableName} (${columns}${foreignKeys ? `, ${foreignKeys}` : ''})`;
+
+ connection.query(query, (error, results, fields) => {
+ if (error) throw error;
+ console.log(`Table ${tableName} created successfully!`);
+ });
+};
+
+const connection = createNewConnection();
+
+// Connect to the database and create the tables
+connection.connect((err) => {
+ if (err) throw err;
+ console.log('Connected to the database.');
+
+
+ useDatabase(connection)
+ .then(() => {
+ createTable('account', accountTable);
+ createTable('account_changes', accountChangesTable, 'FOREIGN KEY (account_number) REFERENCES account(account_number)');
+ })
+ .catch((error) => {
+ console.error('Error setting up the database:', error);
+ })
+ .finally(() => {
+ connection.end();
+ })
+
+});
\ No newline at end of file
diff --git a/Week3/assignment/transactions-insert-values.js b/Week3/assignment/transactions-insert-values.js
new file mode 100644
index 000000000..31223f57b
--- /dev/null
+++ b/Week3/assignment/transactions-insert-values.js
@@ -0,0 +1,47 @@
+import {createNewConnection, useDatabase} from "./connection_query.js";
+
+const connection = createNewConnection();
+
+const accountData = [
+ { account_number: 101, balance: 1000.00 },
+ { account_number: 102, balance: 1500.50 },
+ { account_number: 103, balance: 500.75 },
+];
+
+const accountChangesData = [
+ { account_number: 101, amount: -100.00, changed_date: '2024-08-01 10:00:00', remark: 'ATM Withdrawal' },
+ { account_number: 102, amount: 200.00, changed_date: '2024-08-01 12:00:00', remark: 'Direct Deposit' },
+ { account_number: 103, amount: -50.25, changed_date: '2024-08-02 09:30:00', remark: 'Online Purchase' },
+ { account_number: 101, amount: 300.00, changed_date: '2024-08-02 14:00:00', remark: 'Salary Deposit' },
+];
+
+// Function to insert data into a table
+const insertData = (tableName, data) => {
+ const keys = Object.keys(data[0]);
+ const columns = keys.join(', ');
+ const values = data.map(row => keys.map(key => connection.escape(row[key])).join(', ')).join('), (');
+ const query = `INSERT INTO ${tableName} (${columns}) VALUES (${values})`;
+
+ connection.query(query, (error, results, fields) => {
+ if (error) throw error;
+ console.log(`Data inserted into table ${tableName} successfully!`);
+ });
+};
+
+
+connection.connect((err) => {
+ if (err) throw err;
+ console.log('Connected to the database.');
+
+ useDatabase(connection)
+ .then(() => {
+ insertData('account', accountData);
+ insertData('account_changes', accountChangesData);
+ })
+ .catch((error) => {
+ console.error('Error inserting data into the database:', error);
+ })
+ .finally(() => {
+ connection.end();
+ });
+});
\ No newline at end of file
diff --git a/Week3/homework/mongodb/index.js b/Week3/homework/mongodb/index.js
index 41ee8b618..1a7be1117 100644
--- a/Week3/homework/mongodb/index.js
+++ b/Week3/homework/mongodb/index.js
@@ -1,8 +1,13 @@
+//C:\Users\knowl\Documents\hyf\databases\Week3\homework\mongodb\index.js
const { MongoClient, ServerApiVersion } = require("mongodb");
-
const { seedDatabase } = require("./seedDatabase.js");
+const dotenv = require('dotenv');
+dotenv.config();
+
+
async function createEpisodeExercise(client) {
+
/**
* We forgot to add the last episode of season 9. It has this information:
*
@@ -13,8 +18,17 @@ async function createEpisodeExercise(client) {
// Write code that will add this to the collection!
+ const bobRossCollection = client.db("databaseWeek3").collection("bob_ross_episodes");
+
+ const newEpisode = {
+ episode: "S09E13",
+ title: "MOUNTAIN HIDE-AWAY",
+ elements: ["CIRRUS", "CLOUDS", "CONIFER", "DECIDIOUS", "GRASS", "MOUNTAIN", "MOUNTAINS", "RIVER", "SNOWY_MOUNTAIN", "TREE", "TREES"],
+ };
+
+ const result = await bobRossCollection.insertOne(newEpisode);
console.log(
- `Created season 9 episode 13 and the document got the id ${"TODO: fill in variable here"}`
+ `Created season 9 episode 13 and the document got the id ${result.insertedId}`
);
}
@@ -23,29 +37,33 @@ async function findEpisodesExercises(client) {
* Complete the following exercises.
* The comments indicate what to do and what the result should be!
*/
-
+ const bobRossCollection = client.db("databaseWeek3").collection("bob_ross_episodes");
// Find the title of episode 2 in season 2 [Should be: WINTER SUN]
-
+ const episode2S2 = await bobRossCollection.findOne({ episode: "S02E02" });
console.log(
- `The title of episode 2 in season 2 is ${"TODO: fill in variable here"}`
+ `The title of episode 2 in season 2 is ${episode2S2.title}`
);
// Find the season and episode number of the episode called "BLACK RIVER" [Should be: S02E06]
-
+ const blackRiverEpisode = await bobRossCollection.findOne({ title: "BLACK RIVER" });
console.log(
- `The season and episode number of the "BLACK RIVER" episode is ${"TODO: fill in variable here"}`
+ `The season and episode number of the "BLACK RIVER" episode is ${blackRiverEpisode.episode}`
);
// Find all of the episode titles where Bob Ross painted a CLIFF [Should be: NIGHT LIGHT, EVENING SEASCAPE, SURF'S UP, CLIFFSIDE, BY THE SEA, DEEP WILDERNESS HOME, CRIMSON TIDE, GRACEFUL WATERFALL]
-
+ const cliffEpisodes = await bobRossCollection.find({ elements: "CLIFF" }).toArray();
+ const cliffTitles = cliffEpisodes.map(ep => ep.title).join(", ");
console.log(
- `The episodes that Bob Ross painted a CLIFF are ${"TODO: fill in variable here"}`
+ `The episodes that Bob Ross painted a CLIFF are ${cliffTitles}`
);
// Find all of the episode titles where Bob Ross painted a CLIFF and a LIGHTHOUSE [Should be: NIGHT LIGHT]
-
+ const cliffAndLighthouseEpisodes = await bobRossCollection.find({
+ elements: { $all: ["CLIFF", "LIGHTHOUSE"] },
+ }).toArray();
+ const cliffAndLighthouseTitles = cliffAndLighthouseEpisodes.map(ep => ep.title).join(", ");
console.log(
- `The episodes that Bob Ross painted a CLIFF and a LIGHTHOUSE are ${"TODO: fill in variable here"}`
+ `The episodes that Bob Ross painted a CLIFF and a LIGHTHOUSE are ${cliffAndLighthouseTitles}`
);
}
@@ -56,19 +74,25 @@ async function updateEpisodeExercises(client) {
*
* Note: do NOT change the data.json file
*/
-
+ const bobRossCollection = client.db("databaseWeek3").collection("bob_ross_episodes");
// Episode 13 in season 30 should be called BLUE RIDGE FALLS, yet it is called BLUE RIDGE FALLERS now. Fix that
-
+ const updateResult = await bobRossCollection.updateOne(
+ { episode: "S30E13" },
+ { $set: { title: "BLUE RIDGE FALLS" } }
+ );
console.log(
- `Ran a command to update episode 13 in season 30 and it updated ${"TODO: fill in variable here"} episodes`
+ `Ran a command to update episode 13 in season 30 and it updated ${updateResult.modifiedCount} episodes`
);
// Unfortunately we made a mistake in the arrays and the element type called 'BUSHES' should actually be 'BUSH' as sometimes only one bush was painted.
// Update all of the documents in the collection that have `BUSHES` in the elements array to now have `BUSH`
// It should update 120 episodes!
-
+ const updateBushesResult = await bobRossCollection.updateMany(
+ { elements: "BUSHES" },
+ { $set: { "elements.$": "BUSH" } }
+ );
console.log(
- `Ran a command to update all the BUSHES to BUSH and it updated ${"TODO: fill in variable here"} episodes`
+ `Ran a command to update all the BUSHES to BUSH and it updated ${updateBushesResult.modifiedCount} episodes`
);
}
@@ -77,9 +101,10 @@ async function deleteEpisodeExercise(client) {
* It seems an errand episode has gotten into our data.
* This is episode 14 in season 31. Please remove it and verify that it has been removed!
*/
-
+ const bobRossCollection = client.db("databaseWeek3").collection("bob_ross_episodes");
+ const deleteResult = await bobRossCollection.deleteOne({ episode: "S31E14" });
console.log(
- `Ran a command to delete episode and it deleted ${"TODO: fill in variable here"} episodes`
+ `Ran a command to delete episode and it deleted ${deleteResult.deletedCount} episodes`
);
}
@@ -89,11 +114,7 @@ async function main() {
`You did not set up the environment variables correctly. Did you create a '.env' file and add a package to create it?`
);
}
- const client = new MongoClient(process.env.MONGODB_URL, {
- useNewUrlParser: true,
- useUnifiedTopology: true,
- serverApi: ServerApiVersion.v1,
- });
+ const client = new MongoClient(process.env.MONGODB_URL);
try {
await client.connect();
diff --git a/Week3/homework/mongodb/package-lock.json b/Week3/homework/mongodb/package-lock.json
new file mode 100644
index 000000000..fc7c30d42
--- /dev/null
+++ b/Week3/homework/mongodb/package-lock.json
@@ -0,0 +1,242 @@
+{
+ "name": "mongodb",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "dependencies": {
+ "dotenv": "^16.4.5",
+ "mongodb": "^6.8.0",
+ "mysql": "^2.18.1"
+ }
+ },
+ "node_modules/@mongodb-js/saslprep": {
+ "version": "1.1.8",
+ "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.8.tgz",
+ "integrity": "sha512-qKwC/M/nNNaKUBMQ0nuzm47b7ZYWQHN3pcXq4IIcoSBc2hOIrflAxJduIvvqmhoz3gR2TacTAs8vlsCVPkiEdQ==",
+ "dependencies": {
+ "sparse-bitfield": "^3.0.3"
+ }
+ },
+ "node_modules/@types/webidl-conversions": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz",
+ "integrity": "sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA=="
+ },
+ "node_modules/@types/whatwg-url": {
+ "version": "11.0.5",
+ "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-11.0.5.tgz",
+ "integrity": "sha512-coYR071JRaHa+xoEvvYqvnIHaVqaYrLPbsufM9BF63HkwI5Lgmy2QR8Q5K/lYDYo5AK82wOvSOS0UsLTpTG7uQ==",
+ "dependencies": {
+ "@types/webidl-conversions": "*"
+ }
+ },
+ "node_modules/bignumber.js": {
+ "version": "9.0.0",
+ "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.0.tgz",
+ "integrity": "sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A==",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/bson": {
+ "version": "6.8.0",
+ "resolved": "https://registry.npmjs.org/bson/-/bson-6.8.0.tgz",
+ "integrity": "sha512-iOJg8pr7wq2tg/zSlCCHMi3hMm5JTOxLTagf3zxhcenHsFp+c6uOs6K7W5UE7A4QIJGtqh/ZovFNMP4mOPJynQ==",
+ "engines": {
+ "node": ">=16.20.1"
+ }
+ },
+ "node_modules/core-util-is": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
+ "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="
+ },
+ "node_modules/dotenv": {
+ "version": "16.4.5",
+ "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz",
+ "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://dotenvx.com"
+ }
+ },
+ "node_modules/inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
+ },
+ "node_modules/isarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+ "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="
+ },
+ "node_modules/memory-pager": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz",
+ "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg=="
+ },
+ "node_modules/mongodb": {
+ "version": "6.8.0",
+ "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.8.0.tgz",
+ "integrity": "sha512-HGQ9NWDle5WvwMnrvUxsFYPd3JEbqD3RgABHBQRuoCEND0qzhsd0iH5ypHsf1eJ+sXmvmyKpP+FLOKY8Il7jMw==",
+ "dependencies": {
+ "@mongodb-js/saslprep": "^1.1.5",
+ "bson": "^6.7.0",
+ "mongodb-connection-string-url": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=16.20.1"
+ },
+ "peerDependencies": {
+ "@aws-sdk/credential-providers": "^3.188.0",
+ "@mongodb-js/zstd": "^1.1.0",
+ "gcp-metadata": "^5.2.0",
+ "kerberos": "^2.0.1",
+ "mongodb-client-encryption": ">=6.0.0 <7",
+ "snappy": "^7.2.2",
+ "socks": "^2.7.1"
+ },
+ "peerDependenciesMeta": {
+ "@aws-sdk/credential-providers": {
+ "optional": true
+ },
+ "@mongodb-js/zstd": {
+ "optional": true
+ },
+ "gcp-metadata": {
+ "optional": true
+ },
+ "kerberos": {
+ "optional": true
+ },
+ "mongodb-client-encryption": {
+ "optional": true
+ },
+ "snappy": {
+ "optional": true
+ },
+ "socks": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/mongodb-connection-string-url": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.1.tgz",
+ "integrity": "sha512-XqMGwRX0Lgn05TDB4PyG2h2kKO/FfWJyCzYQbIhXUxz7ETt0I/FqHjUeqj37irJ+Dl1ZtU82uYyj14u2XsZKfg==",
+ "dependencies": {
+ "@types/whatwg-url": "^11.0.2",
+ "whatwg-url": "^13.0.0"
+ }
+ },
+ "node_modules/mysql": {
+ "version": "2.18.1",
+ "resolved": "https://registry.npmjs.org/mysql/-/mysql-2.18.1.tgz",
+ "integrity": "sha512-Bca+gk2YWmqp2Uf6k5NFEurwY/0td0cpebAucFpY/3jhrwrVGuxU2uQFCHjU19SJfje0yQvi+rVWdq78hR5lig==",
+ "dependencies": {
+ "bignumber.js": "9.0.0",
+ "readable-stream": "2.3.7",
+ "safe-buffer": "5.1.2",
+ "sqlstring": "2.3.1"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/process-nextick-args": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
+ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
+ },
+ "node_modules/punycode": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
+ "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/readable-stream": {
+ "version": "2.3.7",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
+ "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
+ "dependencies": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ }
+ },
+ "node_modules/safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
+ },
+ "node_modules/sparse-bitfield": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz",
+ "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==",
+ "dependencies": {
+ "memory-pager": "^1.0.2"
+ }
+ },
+ "node_modules/sqlstring": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.1.tgz",
+ "integrity": "sha512-ooAzh/7dxIG5+uDik1z/Rd1vli0+38izZhGzSa34FwR7IbelPWCCKSNIl8jlL/F7ERvy8CB2jNeM1E9i9mXMAQ==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/string_decoder": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+ "dependencies": {
+ "safe-buffer": "~5.1.0"
+ }
+ },
+ "node_modules/tr46": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/tr46/-/tr46-4.1.1.tgz",
+ "integrity": "sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==",
+ "dependencies": {
+ "punycode": "^2.3.0"
+ },
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
+ },
+ "node_modules/webidl-conversions": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
+ "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/whatwg-url": {
+ "version": "13.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-13.0.0.tgz",
+ "integrity": "sha512-9WWbymnqj57+XEuqADHrCJ2eSXzn8WXIW/YSGaZtb2WKAInQ6CHfaUUcTyyver0p8BDg5StLQq8h1vtZuwmOig==",
+ "dependencies": {
+ "tr46": "^4.1.1",
+ "webidl-conversions": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=16"
+ }
+ }
+ }
+}
diff --git a/Week3/homework/mongodb/package.json b/Week3/homework/mongodb/package.json
new file mode 100644
index 000000000..bd7156aea
--- /dev/null
+++ b/Week3/homework/mongodb/package.json
@@ -0,0 +1,7 @@
+{
+ "dependencies": {
+ "dotenv": "^16.4.5",
+ "mongodb": "^6.8.0",
+ "mysql": "^2.18.1"
+ }
+}
diff --git a/Week3/homework/mongodb/seedDatabase.js b/Week3/homework/mongodb/seedDatabase.js
index 99be6b3d8..5c8336225 100644
--- a/Week3/homework/mongodb/seedDatabase.js
+++ b/Week3/homework/mongodb/seedDatabase.js
@@ -1,4 +1,8 @@
+//C:\Users\knowl\Documents\hyf\databases\Week3\homework\mongodb\seedDatabase.js
const data = require("./data.json");
+const dotenv = require('dotenv');
+dotenv.config();
+
/**
* This function will drop and recreate the collection of sample data in our csv file.
@@ -7,15 +11,21 @@ const data = require("./data.json");
* @param {MongoClient} client - The client that is connected to your database
*/
const seedDatabase = async (client) => {
+ const db = client.db("databaseWeek3"); // Define the db variable
+ const collectionName = "bob_ross_episodes";
+
const hasCollection = await client
.db("databaseWeek3")
.listCollections({ name: "bob_ross_episodes" })
.hasNext();
- if (hasCollection) {
- const bobRossCollection = await client
- .db("databaseWeek3")
- .collection("bob_ross_episodes");
+ if (!hasCollection) {
+ // Create the collection if it doesn't exist
+ await db.createCollection(collectionName);
+ }
+
+ const bobRossCollection = db.collection(collectionName);
+
// Remove all the documents
await bobRossCollection.deleteMany({});
@@ -41,9 +51,7 @@ const seedDatabase = async (client) => {
// Add our documents
await bobRossCollection.insertMany(documents);
- } else {
- throw Error("The collection `bob_ross_episodes` does not exist!");
- }
+
};
module.exports = {
diff --git a/Week3/img.png b/Week3/img.png
new file mode 100644
index 000000000..9acb4e51b
Binary files /dev/null and b/Week3/img.png differ