-
Notifications
You must be signed in to change notification settings - Fork 9
Dalia-assignment-w4 #32
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
base: main
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
|
|
||
| const { MongoClient } = require("mongodb"); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You haven't included any package.json file in your changes. How should we access these third party packages? |
||
|
|
||
| async function connectDB() { | ||
| const client = new MongoClient("mongodb://localhost:27017"); | ||
| await client.connect(); | ||
| const db = client.db("databaseWeek4"); | ||
| return { db, client }; | ||
| } | ||
|
|
||
| module.exports = connectDB; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
|
|
||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Be very careful with leading or trailing whitespaces in file names, e.g. here your file is names |
||
|
|
||
| const connectDB = require("./db"); | ||
|
|
||
| const { | ||
| getPopulationByCountryPerYear, | ||
| getContinentPopulationByYearAndAge | ||
| } = require("./ex1-aggregation/queries"); | ||
|
|
||
| const setup = require("./ex2-transactions/setup"); | ||
| const transfer = require("./ex2-transactions/transfer"); | ||
|
|
||
| async function main() { | ||
| console.log("Running Setup..."); | ||
| await setup(); | ||
|
|
||
| console.log("\nRunning Transfer Transaction..."); | ||
| await transfer(101, 102, 1000, "Test transfer"); | ||
|
|
||
| console.log("\n=== Accounts After Transfer ==="); | ||
| const { db, client } = await connectDB(); | ||
| const accounts = await db.collection("accounts").find().toArray(); | ||
| console.log(accounts); | ||
| await client.close(); | ||
|
|
||
| console.log("\nRunning Aggregation Queries..."); | ||
| const { db: db2, client: client2 } = await connectDB(); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are you sure you need to open/close your connection to the db multiple times? You could do it just once, run your operations, and then close at the end. |
||
|
|
||
| const agg1 = await getPopulationByCountryPerYear(db2, "Netherlands"); | ||
| console.log("\nPopulation by Year for Netherlands:"); | ||
| console.log(agg1); | ||
|
|
||
| const agg2 = await getContinentPopulationByYearAndAge(db2, 2020, "100+"); | ||
| console.log("\nContinents Data for age 100+ in 2020:"); | ||
| console.log(agg2); | ||
|
|
||
| await client2.close(); | ||
| } | ||
|
|
||
| main(); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
|
|
||
| async function getPopulationByCountryPerYear(db, countryName) { | ||
| return await db.collection("population").aggregate([ | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You don't need to change this now - just bear this in mind! Something you may want to consider when you're working with CSV data: Spreadsheets often use Title Case for their headings ( When converting from CSV to database columns you might want to consider your naming conventions. But you do not need to do that for this exercise - jsut something to remember for the future as not following naming conventions will make it harder/less intuitive for other people to work with your databases. |
||
| { $match: { Country: countryName } }, | ||
| { | ||
| $group: { | ||
| _id: "$Year", | ||
| countPopulation: { $sum: { $add: ["$M", "$F"] } } | ||
| } | ||
| }, | ||
| { $sort: { _id: 1 } } | ||
| ]).toArray(); | ||
| } | ||
|
|
||
| async function getContinentPopulationByYearAndAge(db, year, age) { | ||
| return await db.collection("population").aggregate([ | ||
| { $match: { Year: year, Age: age } }, | ||
| { | ||
| $addFields: { | ||
| TotalPopulation: { $add: ["$M", "$F"] } | ||
| } | ||
| } | ||
| ]).toArray(); | ||
| } | ||
|
|
||
| module.exports = { | ||
| getPopulationByCountryPerYear, | ||
| getContinentPopulationByYearAndAge | ||
| }; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
|
|
||
| const connectDB = require("../db"); | ||
|
|
||
| async function setup() { | ||
| const { db, client } = await connectDB(); | ||
| const accounts = db.collection("accounts"); | ||
|
|
||
| await accounts.deleteMany({}); | ||
|
|
||
| await accounts.insertMany([ | ||
| { | ||
| account_number: 101, | ||
| balance: 5000, | ||
| account_changes: [] | ||
| }, | ||
| { | ||
| account_number: 102, | ||
| balance: 2000, | ||
| account_changes: [] | ||
| }, | ||
| { | ||
| account_number: 103, | ||
| balance: 8000, | ||
| account_changes: [] | ||
| } | ||
| ]); | ||
|
|
||
| console.log("Setup done: accounts created."); | ||
| await client.close(); | ||
| } | ||
|
|
||
| module.exports = setup; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,66 @@ | ||
|
|
||
| const connectDB = require("../db"); | ||
|
|
||
| async function transfer(fromAcc, toAcc, amount, remark) { | ||
| const { db, client } = await connectDB(); | ||
| const accounts = db.collection("accounts"); | ||
|
|
||
| const session = client.startSession(); | ||
|
|
||
| try { | ||
| await session.withTransaction(async () => { | ||
| const from = await accounts.findOne({ account_number: fromAcc }, { session }); | ||
| const to = await accounts.findOne({ account_number: toAcc }, { session }); | ||
|
|
||
| if (!from || !to) throw new Error("Account not found."); | ||
| if (from.balance < amount) throw new Error("Insufficient funds."); | ||
|
|
||
| const nextChangeFrom = | ||
| (from.account_changes.at(-1)?.change_number || 0) + 1; | ||
|
|
||
| const nextChangeTo = | ||
| (to.account_changes.at(-1)?.change_number || 0) + 1; | ||
|
|
||
| await accounts.updateOne( | ||
| { account_number: fromAcc }, | ||
| { | ||
| $inc: { balance: -amount }, | ||
| $push: { | ||
| account_changes: { | ||
| change_number: nextChangeFrom, | ||
| amount: -amount, | ||
| changed_date: new Date(), | ||
| remark | ||
| } | ||
| } | ||
| }, | ||
| { session } | ||
| ); | ||
|
|
||
| await accounts.updateOne( | ||
| { account_number: toAcc }, | ||
| { | ||
| $inc: { balance: amount }, | ||
| $push: { | ||
| account_changes: { | ||
| change_number: nextChangeTo, | ||
| amount: amount, | ||
| changed_date: new Date(), | ||
| remark | ||
| } | ||
| } | ||
| }, | ||
| { session } | ||
| ); | ||
| }); | ||
|
|
||
| console.log(`Transfer of ${amount} from ${fromAcc} to ${toAcc} completed.`); | ||
| } catch (err) { | ||
| console.log("Transaction failed:", err.message); | ||
| } finally { | ||
| await session.endSession(); | ||
| await client.close(); | ||
| } | ||
| } | ||
|
|
||
| module.exports = transfer; |
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.
I don't see a data import file in your PR. Can you explain how you got your data into your db?
From the README: