forked from HackYourFuture/databases
-
Notifications
You must be signed in to change notification settings - Fork 6
Yaroslav kazeev w4 databases #25
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
YaroslavKazeev
wants to merge
13
commits into
HackYourAssignment:main
Choose a base branch
from
YaroslavKazeev:YAROSLAV_KAZEEV-w4-Databases
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
a0b8146
DB is seeded
YaroslavKazeev b8eff23
getTotalPopulation works
YaroslavKazeev 618f596
ContinentPopulation completed
YaroslavKazeev 83afd99
cleaned up
YaroslavKazeev 53f4153
ex2 files created
YaroslavKazeev f958294
data inserted into collections
YaroslavKazeev 7392b0c
collections are cleaned up before being populated
YaroslavKazeev 7948d7d
account_changes embedded into accounts
YaroslavKazeev b527da9
cleaned up
YaroslavKazeev d83c05e
transaction in progress
YaroslavKazeev 2848867
transfer function works
YaroslavKazeev 7b422ff
the second updateOne bug fix
YaroslavKazeev de1ba06
the error is rethrown to catch in index.js
YaroslavKazeev File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,100 @@ | ||
| import { MongoClient } from "mongodb"; | ||
| 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) => { | ||
| const data = []; | ||
| fs.createReadStream(fileName) | ||
| .pipe(csv()) | ||
| .on("data", (row) => data.push(row)) | ||
| .on("end", () => resolve(data)) | ||
| .on("error", (err) => reject(err)); | ||
| }); | ||
| } | ||
|
|
||
| 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 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: { | ||
| TotalPopulation: { $add: [{ $toInt: "$M" }, { $toInt: "$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(); | ||
| const db = clientMongo.db("databaseWeek4"); | ||
| const collection = db.collection("population_pyramid"); | ||
| data = await processCSV( | ||
| "./Week4/homework/ex1-aggregation/population_pyramid_1950-2022.csv" | ||
| ); | ||
| await collection.insertMany(data); | ||
| data = await getTotalPopulationByYear(collection, "Netherlands"); | ||
| 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 { | ||
| await clientMongo.close(); | ||
| console.log("Connection to MongoDB closed"); | ||
| } | ||
| } | ||
|
|
||
| main(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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" | ||
| } | ||
| ] | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| 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:", error); | ||
| } finally { | ||
| await clientMongo.close(); | ||
| console.log("Connection to MongoDB closed"); | ||
| } | ||
| } | ||
|
|
||
| main(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| 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.deleteMany({}); | ||
| 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; | ||
| }); | ||
| await account.insertOne(acc); | ||
| } | ||
| return { clientMongo, account }; | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| 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 () => { | ||
| await account.updateOne( | ||
| { account_number: donator_account_number }, | ||
| { | ||
| $inc: { balance: -amount }, | ||
| $push: { account_changes: { amount: -amount, changed_date, remark } }, | ||
| }, | ||
| { session } | ||
| ); | ||
| await account.updateOne( | ||
| { account_number: receiver_account_number }, | ||
| { | ||
| $inc: { balance: amount }, | ||
| $push: { account_changes: { amount: amount, changed_date, remark } }, | ||
| }, | ||
| { session } | ||
| ); | ||
| }, transactionOptions); | ||
| console.log("Transaction committed."); | ||
| } catch (error) { | ||
| console.log("Transaction aborted.", error); | ||
| throw new Error(error); | ||
| } finally { | ||
| await session.endSession(); | ||
| console.log("Transaction completed!"); | ||
| } | ||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion: It's ok in the assignment to use simple error handling (just logging). In real working situation, usually the error will be thrown or return some thing that clearly differentiates the normal state without error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done