This repository contains practical database projects demonstrating:
- MongoDB – Document-oriented NoSQL database.
- Neo4j – Graph-based database.
The projects showcase data modeling, querying, and management in two different paradigms.
The MongoDB section implements an Organizational Location Management System (OLMS).
- Database & collections creation (
Province,Municipality,Facility,Room,Activity,USES). - Insert sample documents into collections.
- Aggregation queries using
$lookup,$unwind,$project, and$map. - Examples:
- Retrieve facilities and their rooms.
- List municipalities with populations above a threshold.
- Show facilities with activity and usage dates.
// Find municipalities with population ≥ 3.5M
db.Municipality.find({ avgPopulation: { $gte: 3500000 } })The Neo4j section implements an Online Location Management System (ONLMS) using a graph model.
-
Creation of Province, Municipality, Facility, Room, and Activity nodes.
-
Establish relationships:
HAS_MUNICIPALITYHAS_FACILITYHAS_ROOMHOSTS_ON_<DATE>
-
Queries for:
- Facilities with their municipalities and provinces.
- Total capacity per municipality.
- Activities with countdown until they occur.
// Retrieve municipalities with population > 4M
MATCH (m:Municipality)
WHERE m.averagePopulation > 4000000
RETURN m.munCode AS MunicipalityCode,
m.name AS MunicipalityName,
m.averagePopulation AS AveragePopulation- Install MongoDB.
- Start MongoDB server.
- Run provided queries in Mongo Shell or MongoDB Compass.
- Install Neo4j Desktop or use Neo4j Aura.
- Start a database instance.
- Run the
.cypherscripts or paste queries into the Neo4j Browser.
Pull requests are welcome. For major changes, please open an issue first to discuss what you’d like to change.
This project is licensed under the Creative Commons Attribution 4.0 International License (CC BY 4.0).
All queries for this project are organized into separate files for easy use.
- 01_create_collections.js – Create database and collections
- 02_insert_records.js – Insert initial records
- 03_facility_with_rooms.js – Facility with related rooms
- 04_municipalities_population.js – Municipalities with population ≥ 3.5M
- 05_facilities_with_usage_dates.js – Facilities with usage dates
- 06_activities_with_facility_details.js – Activities with facility & location details
- 01_create_database.cypher – Create ONLMS database
- 02_create_provinces_municipalities.cypher – Provinces & Municipalities
- 03_create_facilities.cypher – Facilities
- 04_create_rooms.cypher – Rooms
- 05_create_activities.cypher – Activities
- 06_display_all_nodes.cypher – Display all nodes
- 07_total_facility_capacity.cypher – Total facility capacity per municipality
- 08_facilities_with_municipalities_provinces.cypher – Facilities with municipalities & provinces
- 09_activities_days_until.cypher – Activities with days until occurrence
- 10_municipalities_population_over_4M.cypher – Municipalities with population > 4M
// 2.1 Create database
use OLMS
// 2.2 Create collections
db.createCollection("Province")
db.createCollection("Municipality")
db.createCollection("Facility")
db.createCollection("Room")
db.createCollection("Activity")
db.createCollection("USES")
// 2.3 Insert records
db.Province.insertMany([
{provinceCode:"WC", name:"Western Cape"},
{provinceCode:"KZN", name:"KwaZulu-Natal"}
])
db.Municipality.insertMany([
{munCode:"CPT", name:"City of Cape Town", avgPopulation:4005016, provinceCode:"WC"},
{munCode:"ETH", name:"eThekwini Metropolitian Municipality", avgPopulation:3702231, provinceCode:"KZN"}
])
db.Facility.insertMany([
{facilityid:"Arts", name:"Artscape Theatre Centre", address:"D.F. Malan St, Foreshore, Cape Town, 8001", capacity:1500, munCode:"CPT"},
{facilityid:"ICC", name:"Durban ICC", address:"45 Bram Fischer Rd, Durban Central, Durban, 4001", capacity:10000, munCode:"ETH"}
])
db.Room.insertMany([
{roomNo: 1, description: "Hall 1", facilityId: "Arts"},
{roomNo: 2, description: "Hall 2", facilityId: "ICC"}
])
db.Activity.insertMany([
{activityRef: "MUS01", name:"Music Concert"},
{activityRef: "EXH01", name:"Art Exhibition"}
])
db.USES.insertMany([
{facilityId: "Arts", activityRef: "MUS01", Date: new Date("2025-05-20")},
{facilityId: "ICC", activityRef: "EXH01", Date: new Date("2025-06-15")}
])
// 2.4 Facility with related rooms
db.Facility.aggregate([
{$match:{facilityid:"Arts"}},
{$lookup:{from:"Room", localField:"facilityid", foreignField:"facilityId", as:"rooms"}},
{$project:{
_id:true, facilityid:true, name:true, capacity:true, address:true, munCode:true,
rooms:{$map:{input: "$rooms", as:"room", in:{roomNo: "$$room.roomNo", description: "$$room.description"}}}
}}
])
// 2.5 Municipalities with population ≥ 3.5M
db.Municipality.find({avgPopulation:{$gte:3500000}})
// 2.6 Facilities with usage dates
db.USES.aggregate([
{$lookup:{from:"Facility", localField:"facilityId", foreignField:"facilityid", as:"facilityDetails"}},
{$unwind:"$facilityDetails"},
{$project:{
_id:false,
useDate:"$Date",
facilityId:"$facilityDetails.facilityid",
facilityName:"$facilityDetails.name",
capacity:"$facilityDetails.capacity",
address:"$facilityDetails.address"
}}
])
// 2.7 Activities with facility details
db.USES.aggregate([
{$lookup:{from:"Activity", localField:"activityRef", foreignField:"activityRef", as:"activity"}},
{$unwind:"$activity"},
{$lookup:{from:"Facility", localField:"facilityId", foreignField:"facilityid", as:"facility"}},
{$unwind:"$facility"},
{$lookup:{from:"Municipality", localField:"facility.munCode", foreignField:"munCode", as:"municipality"}},
{$unwind:"$municipality"},
{$lookup:{from:"Province", localField:"municipality.provinceCode", foreignField:"provinceCode", as:"province"}},
{$unwind:"$province"},
{$project:{
_id:false,
useDate:"$Date",
activityRef:"$activityRef",
activityName:"$activity.name",
facilityId:"$facilityId",
facilityName:"$facility.name",
capacity:"$facility.capacity",
address:"$facility.address",
municipality:"$municipality.name",
province:"$province.name"
}}
])// 3.1 Create database
CREATE DATABASE ONLMS;
:use ONLMS
// 3.2 Provinces & Municipalities
CREATE
(GP:Province{name:"Gauteng", provinceCode:"GP"}),
(WC:Province{name:"Western Cape", provinceCode:"WC"}),
(JHB:Municipality{name:"City of johannesburg", munCode:"JHB", averagePopulation:4949347, provinceCode:"GP"}),
(CPT:Municipality{name:"City of Cape Town", munCode:"CPT", averagePopulation:4005016, provinceCode:"WC"}),
(WC)-[:HAS_MUNICIPALITY]->(CPT),
(GP)-[:HAS_MUNICIPALITY]->(JHB);
// Facilities
MATCH (JHB:Municipality{name:"City of johannesburg"}), (CPT:Municipality{name:"City of Cape Town"})
CREATE
(UAC:Facility{name:"Ubuntu Art Centre", facilityId:"FAC002", address:"456 Ubuntu Ave", capacity:300, munCode:"CPT"}),
(MCF:Facility{name:"Modise Cultural Facility", facilitId:"FAC001", address:"123 Cultural St", capacity:500, munCode:"JHB"}),
(CPT)-[:HAS_FACILITY]->(UAC),
(JHB)-[:HAS_FACILITY]->(MCF);
// Rooms
MATCH (UAC:Facility{name:"Ubuntu Art Centre"}), (MCF:Facility{name:"Modise Cultural Facility"})
CREATE
(theatre:Room{description:"Theatre", roomNo:"R001", facilityId:"FAC001"}),
(cinema:Room{description:"Cinema", roomNo:"R002", facilityId:"FAC001"}),
(EXH_HALL:Room{description:"Exhibition Hall", roomNo:"R003", facilityId:"FAC002"}),
(workshop:Room{description:"Workshop Room", roomNo:"R004", facilityId:"FAC002"}),
(MCF)-[:HAS_ROOM]->(theatre),
(MCF)-[:HAS_ROOM]->(cinema),
(UAC)-[:HAS_ROOM]->(EXH_HALL),
(UAC)-[:HAS_ROOM]->(workshop);
// Activities
CREATE
(Dance:Activity{name:"IsiZulu Dance Competition", activityRef:"ACT001"}),
(Art:Activity{name:"Art Exhibition", activityRef:"ACT002"}),
(Music:Activity{name:"Music Concert", activityRef:"ACT003"}),
(Theatre:Activity{name:"Theatre Performance", activityRef:"ACT004"});
MATCH (MCF:Facility{name:"Modise Cultural Facility"}), (UAC:Facility{name:"Ubuntu Art Centre"}),
(Dance:Activity{name:"IsiZulu Dance Competition"}), (Art:Activity{name:"Art Exhibition"}),
(Music:Activity{name:"Music Concert"}),(theatre:Activity{name:"Theatre Performance"})
CREATE
(MCF)-[:HOSTS_ON_2025_05_20{facilityId:"fac001", activityRef:"ACT001", Date:"2025-05-20"}]->(Dance),
(MCF)-[:HOSTS_ON_2025_06_20{facilityId:"fac001", activityRef:"ACT002", Date:"2025-06-20"}]->(Art),
(UAC)-[:HOSTS_ON_2025_10_20{facilityId:"fac002", activityRef:"ACT003", Date:"2025-10-20"}]->(Music),
(UAC)-[:HOSTS_ON_2025_12_12{facilityId:"fac002", activityRef:"ACT004", Date:"2025-12-12"}]->(theatre);
// 3.3 Display all nodes
MATCH (all_nodes) RETURN all_nodes;
// 3.4 Total facility capacity per municipality
MATCH (m:Municipality)-[:HAS_FACILITY]->(f:Facility)
RETURN m.name AS MunicipalityName, f.capacity AS Capacity;
// 3.5 Facilities with municipalities and provinces
MATCH (p:Province)-[:HAS_MUNICIPALITY]->(m:Municipality)-[:HAS_FACILITY]->(f:Facility)
RETURN f.name AS FacilityName, m.name AS MunicipalityName, p.name AS ProvinceName;
// 3.6 Activities with days until occurrence
MATCH (f:Facility)-[r]->(a:Activity)
RETURN a.name AS ActivityName, f.name AS FacilityName, r.Date AS ActivityDate,
duration.inDays(date(), date(r.Date)).days AS DaysUntilActivity;
// 3.7 Municipalities with population > 4M
MATCH (m:Municipality)
WHERE m.averagePopulation > 4000000
RETURN m.munCode AS MunicipalityCode, m.name AS MunicipalityName, m.averagePopulation AS AveragePopulation;