From a0b8146700e0c34b09b41dacc8a81bb05f1e36e1 Mon Sep 17 00:00:00 2001 From: Yaroslav <1.yaroslav.kazeev@gmail.com> Date: Sun, 14 Sep 2025 01:50:40 +0200 Subject: [PATCH 01/13] DB is seeded --- Week4/homework/ex1-aggregation/index.js | 35 +++++ package-lock.json | 185 ++++++++++++++++++++++++ package.json | 8 + 3 files changed, 228 insertions(+) create mode 100644 Week4/homework/ex1-aggregation/index.js create mode 100644 package-lock.json create mode 100644 package.json diff --git a/Week4/homework/ex1-aggregation/index.js b/Week4/homework/ex1-aggregation/index.js new file mode 100644 index 000000000..4ef55d7c0 --- /dev/null +++ b/Week4/homework/ex1-aggregation/index.js @@ -0,0 +1,35 @@ +import { MongoClient } from "mongodb"; +import "dotenv/config"; +const clientMongo = new MongoClient(process.env.MONGODB_URL); +import fs from "fs"; +import csv from "csv-parser"; + +async function processCSV(fileName) { + return new Promise((resolve, reject) => { + const data = []; + fs.createReadStream(fileName) + .pipe(csv()) + .on("data", (row) => data.push(row)) + .on("end", () => resolve(data)) + .on("error", (err) => reject(err)); + }); +} + +async function main() { + try { + await clientMongo.connect(); + const db = clientMongo.db("databaseWeek4"); + const collection = db.collection("population_pyramid"); + let data = await processCSV( + "./Week4/homework/ex1-aggregation/population_pyramid_1950-2022.csv" + ); + await collection.insertMany(data); + } catch (error) { + console.error("Error connecting to MongoDB:", error); + } finally { + await clientMongo.close(); + console.log("Connection to MongoDB closed"); + } +} + +main(); diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 000000000..da3a745b9 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,185 @@ +{ + "name": "databases-Cohort53", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "dependencies": { + "csv-parser": "^3.2.0", + "dotenv": "^17.2.2", + "mongodb": "^6.19.0" + } + }, + "node_modules/@mongodb-js/saslprep": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.3.0.tgz", + "integrity": "sha512-zlayKCsIjYb7/IdfqxorK5+xUMyi4vOKcFy10wKJYc63NSdKI8mNME+uJqfatkPmOSMMUiojrL58IePKBm3gvQ==", + "license": "MIT", + "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==", + "license": "MIT" + }, + "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==", + "license": "MIT", + "dependencies": { + "@types/webidl-conversions": "*" + } + }, + "node_modules/bson": { + "version": "6.10.4", + "resolved": "https://registry.npmjs.org/bson/-/bson-6.10.4.tgz", + "integrity": "sha512-WIsKqkSC0ABoBJuT1LEX+2HEvNmNKKgnTAyd0fL8qzK4SH2i9NXg+t08YtdZp/V9IZ33cxe3iV4yM0qg8lMQng==", + "license": "Apache-2.0", + "engines": { + "node": ">=16.20.1" + } + }, + "node_modules/csv-parser": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/csv-parser/-/csv-parser-3.2.0.tgz", + "integrity": "sha512-fgKbp+AJbn1h2dcAHKIdKNSSjfp43BZZykXsCjzALjKy80VXQNHPFJ6T9Afwdzoj24aMkq8GwDS7KGcDPpejrA==", + "license": "MIT", + "bin": { + "csv-parser": "bin/csv-parser" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/dotenv": { + "version": "17.2.2", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.2.tgz", + "integrity": "sha512-Sf2LSQP+bOlhKWWyhFsn0UsfdK/kCWRv1iuA2gXAwt3dyNabr6QSj00I2V10pidqz69soatm9ZwZvpQMTIOd5Q==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "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==", + "license": "MIT" + }, + "node_modules/mongodb": { + "version": "6.19.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.19.0.tgz", + "integrity": "sha512-H3GtYujOJdeKIMLKBT9PwlDhGrQfplABNF1G904w6r5ZXKWyv77aB0X9B+rhmaAwjtllHzaEkvi9mkGVZxs2Bw==", + "license": "Apache-2.0", + "dependencies": { + "@mongodb-js/saslprep": "^1.1.9", + "bson": "^6.10.4", + "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 || ^2.0.0", + "gcp-metadata": "^5.2.0", + "kerberos": "^2.0.1", + "mongodb-client-encryption": ">=6.0.0 <7", + "snappy": "^7.3.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.2", + "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.2.tgz", + "integrity": "sha512-rMO7CGo/9BFwyZABcKAWL8UJwH/Kc2x0g72uhDWzG48URRax5TCIcJ7Rc3RZqffZzO/Gwff/jyKwCU9TN8gehA==", + "license": "Apache-2.0", + "dependencies": { + "@types/whatwg-url": "^11.0.2", + "whatwg-url": "^14.1.0 || ^13.0.0" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "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==", + "license": "MIT", + "dependencies": { + "memory-pager": "^1.0.2" + } + }, + "node_modules/tr46": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.1.1.tgz", + "integrity": "sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==", + "license": "MIT", + "dependencies": { + "punycode": "^2.3.1" + }, + "engines": { + "node": ">=18" + } + }, + "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==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-url": { + "version": "14.2.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.2.0.tgz", + "integrity": "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==", + "license": "MIT", + "dependencies": { + "tr46": "^5.1.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=18" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 000000000..5822ae68d --- /dev/null +++ b/package.json @@ -0,0 +1,8 @@ +{ + "dependencies": { + "csv-parser": "^3.2.0", + "dotenv": "^17.2.2", + "mongodb": "^6.19.0" + }, + "type": "module" +} From b8eff2310e4bb8326b36c3e71cb837f3f33b6c44 Mon Sep 17 00:00:00 2001 From: Yaroslav <1.yaroslav.kazeev@gmail.com> Date: Sun, 14 Sep 2025 11:36:20 +0200 Subject: [PATCH 02/13] getTotalPopulation works --- Week4/homework/ex1-aggregation/index.js | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/Week4/homework/ex1-aggregation/index.js b/Week4/homework/ex1-aggregation/index.js index 4ef55d7c0..01aec1034 100644 --- a/Week4/homework/ex1-aggregation/index.js +++ b/Week4/homework/ex1-aggregation/index.js @@ -3,6 +3,7 @@ import "dotenv/config"; const clientMongo = new MongoClient(process.env.MONGODB_URL); import fs from "fs"; import csv from "csv-parser"; +let data; async function processCSV(fileName) { return new Promise((resolve, reject) => { @@ -15,15 +16,37 @@ async function processCSV(fileName) { }); } +async function getTotalPopulationByYear(collection, country) { + const result = await collection + .aggregate([ + { $match: { Country: country } }, + { + $group: { + _id: { $toInt: "$Year" }, + countPopulation: { + $sum: { + $add: [{ $toInt: "$M" }, { $toInt: "$F" }], + }, + }, + }, + }, + { $sort: { _id: 1 } }, + ]) + .toArray(); + return result; +} + async function main() { try { await clientMongo.connect(); const db = clientMongo.db("databaseWeek4"); const collection = db.collection("population_pyramid"); - let data = await processCSV( + data = await processCSV( "./Week4/homework/ex1-aggregation/population_pyramid_1950-2022.csv" ); await collection.insertMany(data); + data = await getTotalPopulationByYear(collection, "Netherlands"); + console.log(JSON.stringify(data, null, 2)); } catch (error) { console.error("Error connecting to MongoDB:", error); } finally { From 618f596da7a466ef38a14e090aa9160f058108f1 Mon Sep 17 00:00:00 2001 From: Yaroslav <1.yaroslav.kazeev@gmail.com> Date: Sun, 14 Sep 2025 12:22:36 +0200 Subject: [PATCH 03/13] ContinentPopulation completed --- Week4/homework/ex1-aggregation/index.js | 50 ++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/Week4/homework/ex1-aggregation/index.js b/Week4/homework/ex1-aggregation/index.js index 01aec1034..a4e9dced4 100644 --- a/Week4/homework/ex1-aggregation/index.js +++ b/Week4/homework/ex1-aggregation/index.js @@ -36,6 +36,46 @@ async function getTotalPopulationByYear(collection, country) { return result; } +async function getContinentsPopulation(collection, year, age) { + const result = await collection + .aggregate([ + { + $match: { + Year: year.toString(), + Age: age.toString(), + // Filter only continents by checking if Country is uppercase + $expr: { + $eq: ["$Country", { $toUpper: "$Country" }], + }, + }, + }, + { + $addFields: { + M: { $toInt: "$M" }, + F: { $toInt: "$F" }, + }, + }, + { + $addFields: { + TotalPopulation: { $add: ["$M", "$F"] }, + }, + }, + { + $project: { + _id: 1, + Country: 1, + Year: 1, + Age: 1, + M: 1, + F: 1, + TotalPopulation: 1, + }, + }, + ]) + .toArray(); + return result; +} + async function main() { try { await clientMongo.connect(); @@ -46,7 +86,15 @@ async function main() { ); await collection.insertMany(data); data = await getTotalPopulationByYear(collection, "Netherlands"); - console.log(JSON.stringify(data, null, 2)); + console.log( + "\nPopulation by Year (Netherlands):\n", + JSON.stringify(data, null, 2) + ); + data = await getContinentsPopulation(collection, "2020", "100+"); + console.log( + "\nPopulation by Continent (2020, 100+):\n", + JSON.stringify(data, null, 2) + ); } catch (error) { console.error("Error connecting to MongoDB:", error); } finally { From 83afd999b209ee685599c60308871ec97b073c2a Mon Sep 17 00:00:00 2001 From: Yaroslav <1.yaroslav.kazeev@gmail.com> Date: Sun, 14 Sep 2025 12:31:16 +0200 Subject: [PATCH 04/13] cleaned up --- Week4/homework/ex1-aggregation/index.js | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/Week4/homework/ex1-aggregation/index.js b/Week4/homework/ex1-aggregation/index.js index a4e9dced4..5adf824d3 100644 --- a/Week4/homework/ex1-aggregation/index.js +++ b/Week4/homework/ex1-aggregation/index.js @@ -51,13 +51,7 @@ async function getContinentsPopulation(collection, year, age) { }, { $addFields: { - M: { $toInt: "$M" }, - F: { $toInt: "$F" }, - }, - }, - { - $addFields: { - TotalPopulation: { $add: ["$M", "$F"] }, + TotalPopulation: { $add: [{ $toInt: "$M" }, { $toInt: "$F" }] }, }, }, { From 53f4153e63bc5e382bd29b793d93bd5c56d7fa96 Mon Sep 17 00:00:00 2001 From: Yaroslav <1.yaroslav.kazeev@gmail.com> Date: Sun, 14 Sep 2025 22:20:00 +0200 Subject: [PATCH 05/13] ex2 files created --- Week4/homework/ex2-transactions/index.js | 0 Week4/homework/ex2-transactions/setup.js | 0 Week4/homework/ex2-transactions/transfer.js | 0 3 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 Week4/homework/ex2-transactions/index.js create mode 100644 Week4/homework/ex2-transactions/setup.js create mode 100644 Week4/homework/ex2-transactions/transfer.js diff --git a/Week4/homework/ex2-transactions/index.js b/Week4/homework/ex2-transactions/index.js new file mode 100644 index 000000000..e69de29bb diff --git a/Week4/homework/ex2-transactions/setup.js b/Week4/homework/ex2-transactions/setup.js new file mode 100644 index 000000000..e69de29bb diff --git a/Week4/homework/ex2-transactions/transfer.js b/Week4/homework/ex2-transactions/transfer.js new file mode 100644 index 000000000..e69de29bb From f9582940d4fe5f8f7f329e3a635409b18c2fb3c1 Mon Sep 17 00:00:00 2001 From: Yaroslav <1.yaroslav.kazeev@gmail.com> Date: Mon, 15 Sep 2025 00:32:52 +0200 Subject: [PATCH 06/13] data inserted into collections --- Week4/homework/ex2-transactions/data.json | 41 +++++++++++++++++++++++ Week4/homework/ex2-transactions/index.js | 14 ++++++++ Week4/homework/ex2-transactions/setup.js | 17 ++++++++++ 3 files changed, 72 insertions(+) create mode 100644 Week4/homework/ex2-transactions/data.json diff --git a/Week4/homework/ex2-transactions/data.json b/Week4/homework/ex2-transactions/data.json new file mode 100644 index 000000000..7c813b96d --- /dev/null +++ b/Week4/homework/ex2-transactions/data.json @@ -0,0 +1,41 @@ +{ + "accounts": [ + { "account_number": 101, "balance": 5000 }, + { "account_number": 102, "balance": 12000 }, + { "account_number": 103, "balance": 7500 }, + { "account_number": 104, "balance": 3000 }, + { "account_number": 105, "balance": 9500 } + ], + "account_changes": [ + { + "account_number": 101, + "amount": 1000, + "changed_date": "2025-09-01", + "remark": "Salary deposit" + }, + { + "account_number": 102, + "amount": -500, + "changed_date": "2025-09-02", + "remark": "Grocery shopping" + }, + { + "account_number": 103, + "amount": 2000, + "changed_date": "2025-09-03", + "remark": "Freelance payment" + }, + { + "account_number": 104, + "amount": -1000, + "changed_date": "2025-09-04", + "remark": "Rent payment" + }, + { + "account_number": 105, + "amount": 1500, + "changed_date": "2025-09-05", + "remark": "Gift received" + } + ] +} diff --git a/Week4/homework/ex2-transactions/index.js b/Week4/homework/ex2-transactions/index.js index e69de29bb..4f6ce1014 100644 --- a/Week4/homework/ex2-transactions/index.js +++ b/Week4/homework/ex2-transactions/index.js @@ -0,0 +1,14 @@ +import { setup } from "./setup.js"; +let clientMongo, account, accountChanges; +async function main() { + try { + ({ clientMongo, account, accountChanges } = await setup()); + } catch (error) { + console.error("Error connecting to MongoDB:", error); + } finally { + await clientMongo.close(); + console.log("Connection to MongoDB closed"); + } +} + +main(); diff --git a/Week4/homework/ex2-transactions/setup.js b/Week4/homework/ex2-transactions/setup.js index e69de29bb..f9288375e 100644 --- a/Week4/homework/ex2-transactions/setup.js +++ b/Week4/homework/ex2-transactions/setup.js @@ -0,0 +1,17 @@ +import { MongoClient } from "mongodb"; +import "dotenv/config"; +import fs from "fs"; + +export async function setup() { + const { accounts, account_changes } = JSON.parse( + fs.readFileSync("./Week4/homework/ex2-transactions/data.json") + ); + const clientMongo = new MongoClient(process.env.MONGODB_URL); + await clientMongo.connect(); + const db = clientMongo.db("databaseWeek4"); + const account = await db.createCollection("accounts"); + await account.insertMany(accounts); + const accountChanges = await db.createCollection("account_changes"); + await accountChanges.insertMany(account_changes); + return { clientMongo, account, accountChanges }; +} From 7392b0cbd36ee7fa325aaf1e6aac6074a3ef5e44 Mon Sep 17 00:00:00 2001 From: Yaroslav <1.yaroslav.kazeev@gmail.com> Date: Mon, 15 Sep 2025 00:41:07 +0200 Subject: [PATCH 07/13] collections are cleaned up before being populated --- Week4/homework/ex2-transactions/setup.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Week4/homework/ex2-transactions/setup.js b/Week4/homework/ex2-transactions/setup.js index f9288375e..8bc888bb6 100644 --- a/Week4/homework/ex2-transactions/setup.js +++ b/Week4/homework/ex2-transactions/setup.js @@ -10,8 +10,10 @@ export async function setup() { await clientMongo.connect(); const db = clientMongo.db("databaseWeek4"); const account = await db.createCollection("accounts"); + await account.deleteMany({}); await account.insertMany(accounts); const accountChanges = await db.createCollection("account_changes"); + await accountChanges.deleteMany({}); await accountChanges.insertMany(account_changes); return { clientMongo, account, accountChanges }; } From 7948d7d431e234708e7f928eec5f4e0aad0d659f Mon Sep 17 00:00:00 2001 From: Yaroslav <1.yaroslav.kazeev@gmail.com> Date: Mon, 15 Sep 2025 10:24:44 +0200 Subject: [PATCH 08/13] account_changes embedded into accounts --- Week4/homework/ex2-transactions/index.js | 4 ++-- Week4/homework/ex2-transactions/setup.js | 20 +++++++++++++++----- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/Week4/homework/ex2-transactions/index.js b/Week4/homework/ex2-transactions/index.js index 4f6ce1014..0d62da095 100644 --- a/Week4/homework/ex2-transactions/index.js +++ b/Week4/homework/ex2-transactions/index.js @@ -1,8 +1,8 @@ import { setup } from "./setup.js"; -let clientMongo, account, accountChanges; +let clientMongo, account; async function main() { try { - ({ clientMongo, account, accountChanges } = await setup()); + ({ clientMongo, account } = await setup()); } catch (error) { console.error("Error connecting to MongoDB:", error); } finally { diff --git a/Week4/homework/ex2-transactions/setup.js b/Week4/homework/ex2-transactions/setup.js index 8bc888bb6..c9c38d886 100644 --- a/Week4/homework/ex2-transactions/setup.js +++ b/Week4/homework/ex2-transactions/setup.js @@ -11,9 +11,19 @@ export async function setup() { const db = clientMongo.db("databaseWeek4"); const account = await db.createCollection("accounts"); await account.deleteMany({}); - await account.insertMany(accounts); - const accountChanges = await db.createCollection("account_changes"); - await accountChanges.deleteMany({}); - await accountChanges.insertMany(account_changes); - return { clientMongo, account, accountChanges }; + // await account.insertMany(accounts); + for (const acc of accounts) { + acc.account_changes = account_changes + .filter((a) => a.account_number === acc.account_number) + .map((a) => { + delete a.account_number; + return a; + }); + console.log(acc); + await account.insertOne(acc); + } + // const accountChanges = await db.createCollection("account_changes"); + // await accountChanges.deleteMany({}); + // await accountChanges.insertMany(account_changes); + return { clientMongo, account }; } From b527da9d69eadb6361537593312cce0053b41119 Mon Sep 17 00:00:00 2001 From: Yaroslav <1.yaroslav.kazeev@gmail.com> Date: Mon, 15 Sep 2025 10:26:01 +0200 Subject: [PATCH 09/13] cleaned up --- Week4/homework/ex2-transactions/setup.js | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Week4/homework/ex2-transactions/setup.js b/Week4/homework/ex2-transactions/setup.js index c9c38d886..e35972546 100644 --- a/Week4/homework/ex2-transactions/setup.js +++ b/Week4/homework/ex2-transactions/setup.js @@ -11,7 +11,6 @@ export async function setup() { const db = clientMongo.db("databaseWeek4"); const account = await db.createCollection("accounts"); await account.deleteMany({}); - // await account.insertMany(accounts); for (const acc of accounts) { acc.account_changes = account_changes .filter((a) => a.account_number === acc.account_number) @@ -19,11 +18,7 @@ export async function setup() { delete a.account_number; return a; }); - console.log(acc); await account.insertOne(acc); } - // const accountChanges = await db.createCollection("account_changes"); - // await accountChanges.deleteMany({}); - // await accountChanges.insertMany(account_changes); return { clientMongo, account }; } From d83c05ee38f5a6d8d238e1c34c0c52716e35e15e Mon Sep 17 00:00:00 2001 From: Yaroslav <1.yaroslav.kazeev@gmail.com> Date: Mon, 15 Sep 2025 11:23:02 +0200 Subject: [PATCH 10/13] transaction in progress --- Week4/homework/ex2-transactions/index.js | 9 +++ .../homework/ex2-transactions/transaction.js | 48 +++++++++++++++ Week4/homework/ex2-transactions/transfer.js | 60 +++++++++++++++++++ 3 files changed, 117 insertions(+) create mode 100644 Week4/homework/ex2-transactions/transaction.js diff --git a/Week4/homework/ex2-transactions/index.js b/Week4/homework/ex2-transactions/index.js index 0d62da095..a74409be9 100644 --- a/Week4/homework/ex2-transactions/index.js +++ b/Week4/homework/ex2-transactions/index.js @@ -1,8 +1,17 @@ import { setup } from "./setup.js"; +import { transfer } from "./transfer.js"; let clientMongo, account; async function main() { try { ({ clientMongo, account } = await setup()); + const transactionDetails = { + donator_account_number: 101, + receiver_account_number: 102, + amount: 1000, + changed_date: new Date().toISOString().slice(0, 10), // 'YYYY-MM-DD' + remark: `Transfer from 101 to 102`, + }; + await transfer(clientMongo, account, transactionDetails); } catch (error) { console.error("Error connecting to MongoDB:", error); } finally { diff --git a/Week4/homework/ex2-transactions/transaction.js b/Week4/homework/ex2-transactions/transaction.js new file mode 100644 index 000000000..93f4e8f91 --- /dev/null +++ b/Week4/homework/ex2-transactions/transaction.js @@ -0,0 +1,48 @@ +import { Client } from "pg"; +const config = { + host: "localhost", + user: "hyfuser", + password: "hyfpassword", + database: "transactions_week3", + port: 5432, +}; +const client = new Client(config); + +async function seedDatabase(client) { + try { + await client.connect(); + console.log("Connected to PostgreSQL database!"); + + const donator_account_number = 101; + const receiver_account_number = 102; + const amount = 1000; + const changed_date = new Date().toISOString().slice(0, 10); // 'YYYY-MM-DD' + const remark = `Transfer from 101 to 102`; + + await client.query("BEGIN"); + await client.query( + "UPDATE ACCOUNT SET balance = balance - $1 WHERE account_number = $2", + [amount, donator_account_number] + ); + await client.query( + "UPDATE ACCOUNT SET balance = balance + $1 WHERE account_number = $2", + [amount, receiver_account_number] + ); + await client.query( + "INSERT INTO account_changes(account_number, amount, changed_date, remark) VALUES($1, $2, $3, $4)", + [donator_account_number, -amount, changed_date, remark] + ); + await client.query( + "INSERT INTO account_changes(account_number, amount, changed_date, remark) VALUES($1, $2, $3, $4)", + [receiver_account_number, amount, changed_date, remark] + ); + await client.query("COMMIT"); + console.log("Transaction completed!"); + } catch (error) { + console.error("Error seeding database:", error); + } finally { + await client.end(); + } +} + +seedDatabase(client); diff --git a/Week4/homework/ex2-transactions/transfer.js b/Week4/homework/ex2-transactions/transfer.js index e69de29bb..9f25123e5 100644 --- a/Week4/homework/ex2-transactions/transfer.js +++ b/Week4/homework/ex2-transactions/transfer.js @@ -0,0 +1,60 @@ +export async function transfer(clientMongo, account, transactionDetails) { + const { + donator_account_number, + receiver_account_number, + amount, + changed_date, + remark, + } = transactionDetails; + const session = clientMongo.startSession(); + const transactionOptions = { + readPreference: "primary", + readConcern: { level: "local" }, + writeConcern: { w: "majority" }, + }; + try { + await session.withTransaction(async () => { + // Deduct from donator + await account.updateOne( + { account_number: donator_account_number }, + { $inc: { balance: -amount } }, + { session } + ); + + // Add to receiver + await account.updateOne( + { account_number: receiver_account_number }, + { $inc: { balance: amount } }, + { session } + ); + + // Log donator change + await clientMongo.db().collection("account_changes").insertOne( + { + account_number: donator_account_number, + amount: -amount, + changed_date, + remark, + }, + { session } + ); + + // Log receiver change + await clientMongo.db().collection("account_changes").insertOne( + { + account_number: receiver_account_number, + amount, + changed_date, + remark, + }, + { session } + ); + }, transactionOptions); + console.log("Transaction committed."); + } catch (e) { + console.log("Transaction aborted.", e); + } finally { + await session.endSession(); + console.log("Transaction completed!"); + } +} From 284886713e525fa92ac47d68d08a947e67e1fb9b Mon Sep 17 00:00:00 2001 From: Yaroslav <1.yaroslav.kazeev@gmail.com> Date: Mon, 15 Sep 2025 11:50:11 +0200 Subject: [PATCH 11/13] transfer function works --- Week4/homework/ex2-transactions/transfer.js | 33 +++++---------------- 1 file changed, 7 insertions(+), 26 deletions(-) diff --git a/Week4/homework/ex2-transactions/transfer.js b/Week4/homework/ex2-transactions/transfer.js index 9f25123e5..aff527eab 100644 --- a/Week4/homework/ex2-transactions/transfer.js +++ b/Week4/homework/ex2-transactions/transfer.js @@ -14,45 +14,26 @@ export async function transfer(clientMongo, account, transactionDetails) { }; try { await session.withTransaction(async () => { - // Deduct from donator await account.updateOne( { account_number: donator_account_number }, - { $inc: { balance: -amount } }, + { + $inc: { balance: -amount }, + $push: { account_changes: { amount: -amount, changed_date, remark } }, + }, { session } ); - - // Add to receiver await account.updateOne( { account_number: receiver_account_number }, { $inc: { balance: amount } }, - { session } - ); - - // Log donator change - await clientMongo.db().collection("account_changes").insertOne( - { - account_number: donator_account_number, - amount: -amount, - changed_date, - remark, - }, - { session } - ); - - // Log receiver change - await clientMongo.db().collection("account_changes").insertOne( { - account_number: receiver_account_number, - amount, - changed_date, - remark, + $push: { account_changes: { amount: amount, changed_date, remark } }, }, { session } ); }, transactionOptions); console.log("Transaction committed."); - } catch (e) { - console.log("Transaction aborted.", e); + } catch (error) { + console.log("Transaction aborted.", error); } finally { await session.endSession(); console.log("Transaction completed!"); From 7b422ffad17d1769f9231d4a80365621f48cee1b Mon Sep 17 00:00:00 2001 From: Yaroslav <1.yaroslav.kazeev@gmail.com> Date: Fri, 19 Sep 2025 22:24:42 +0200 Subject: [PATCH 12/13] the second updateOne bug fix --- Week4/homework/ex2-transactions/transfer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Week4/homework/ex2-transactions/transfer.js b/Week4/homework/ex2-transactions/transfer.js index aff527eab..5e0a25dd7 100644 --- a/Week4/homework/ex2-transactions/transfer.js +++ b/Week4/homework/ex2-transactions/transfer.js @@ -24,8 +24,8 @@ export async function transfer(clientMongo, account, transactionDetails) { ); await account.updateOne( { account_number: receiver_account_number }, - { $inc: { balance: amount } }, { + $inc: { balance: amount }, $push: { account_changes: { amount: amount, changed_date, remark } }, }, { session } From de1ba06bbe79566be3d49634d6e229129b919d4b Mon Sep 17 00:00:00 2001 From: Yaroslav <1.yaroslav.kazeev@gmail.com> Date: Fri, 19 Sep 2025 22:32:28 +0200 Subject: [PATCH 13/13] the error is rethrown to catch in index.js --- Week4/homework/ex2-transactions/index.js | 2 +- Week4/homework/ex2-transactions/transfer.js | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Week4/homework/ex2-transactions/index.js b/Week4/homework/ex2-transactions/index.js index a74409be9..61b11d0df 100644 --- a/Week4/homework/ex2-transactions/index.js +++ b/Week4/homework/ex2-transactions/index.js @@ -13,7 +13,7 @@ async function main() { }; await transfer(clientMongo, account, transactionDetails); } catch (error) { - console.error("Error connecting to MongoDB:", error); + console.error("Error:", error); } finally { await clientMongo.close(); console.log("Connection to MongoDB closed"); diff --git a/Week4/homework/ex2-transactions/transfer.js b/Week4/homework/ex2-transactions/transfer.js index 5e0a25dd7..9c28bd2a7 100644 --- a/Week4/homework/ex2-transactions/transfer.js +++ b/Week4/homework/ex2-transactions/transfer.js @@ -34,6 +34,7 @@ export async function transfer(clientMongo, account, transactionDetails) { console.log("Transaction committed."); } catch (error) { console.log("Transaction aborted.", error); + throw new Error(error); } finally { await session.endSession(); console.log("Transaction completed!");