Simple hospital API made to demonstrate DynamoDB capabilities.
- DynamoDB data modeling
- Single Table Design
- One-to-many relationships
- Many-to-many relationships
- Cross-partition querying
- Pagination and Sorting strategies
- Singleton strategy
- Incomplete migration helper and some more interesting stuff :)
- NestJS
- Vertical slice architecture
- CQS
Prerequisites: This example requires only node and docker installed.
A very simple ERD was used for this project. However, it was more than enough to demonstrate a lot of different DynamoDB concepts based on the access patterns.
Initial entities included:
- Doctor
- Patient
- Test
which was obvious from the ERD. As different access patterns were modeled two more entities were added:
- DoctorPatient - to address many-to-many relationship between Doctors and Patients
- Specialization - singleton that has a set of all medical departments in a hospital
Entity chart is used to keep track of all the different item types that we are going to store in our table.
ENTITY | PK | SK |
---|---|---|
Patient | PATIENT#<PatientId> | PATIENT#<PatientId> |
Doctor | DOCTOR#<DoctorId> | DOCTOR#<DoctorId> |
Test | PATIENT#<PatientId> | #TEST#<KSUID> |
Specialization | DOCTOR | SPECIALIZATION |
DoctorPatient | DOCTOR#<DoctorId> | PATIENT#<PatientId> |
ENTITY | ACCESS PATTERN | INDEX | PARAMS | NOTES |
---|---|---|---|---|
Patient | Get | / | pk: PATIENT#<PatientId> sk: PATIENT#<PatientId> | / |
List - sort by created time | GSI2 | pk: PATIENT#<TRUNC_TO_WEEK(CreatedAt)> sk: PATIENT#<CreatedAt> | We get 100 new patients weekly | |
List - sort by lastname | GSI1 | pk: PATIENT#<TRUNC(LastName)> sk: PATIENT#<LastName-CreatedAt> | / | |
Create | / | pk: PATIENT#<PatientId> sk: PATIENT#<PatientId> | / | |
Update | / | pk: PATIENT#<PatientId> sk: PATIENT#<PatientId> | / | |
Delete | / | pk: PATIENT#<PatientId> sk: PATIENT#<PatientId> | / | |
List of Patients for a specific Doctor | GSI3 | pk: PATIENT#<PatientId> sk: DOCTOR#<DoctorId> | / | |
Doctor | Get | / | pk: DOCTOR#<DoctorId> sk: DOCTOR#<Specialization> | / |
List - sort and filter by specialization | GSI2 | pk: SPECIALIZATION#<Specialization> sk: <Specialization>#<DoctorId> | Cross-partition query of doctors. Sort in order of alphabetically sorted specializations. | |
Create | / | pk: DOCTOR#<DoctorId> sk: DOCTOR#<DoctorId> | / | |
Update | / | pk: DOCTOR#<DoctorId> sk: DOCTOR#<DoctorId> | / | |
Delete | / | pk: DOCTOR#<DoctorId> sk: DOCTOR#<DoctorId> | / | |
List Doctors for specific Patient | GSI3 | pk: PATIENT#<PatientId> sk: DOCTOR#<DoctorId> | / | |
Test | Get test for patient | / | pk: PATIENT#<PatientId> sk: #TEST#<KSUID> | / |
Create test for patient | / | pk: PATIENT#<PatientId> sk: #TEST#<KSUID> | / | |
List tests for patient | / | pk: PATIENT#<PatientId> sk: #TEST#<KSUID> | / | |
List tests performed by specific doctor | GSI1 | pk: DOCTOR#<DoctorId> sk: #TEST#<KSUID> | GSI1 is added to both doctors and tests | |
Specialization | Get | / | pk: DOCTOR sk: SPECIALIZATION | Specialization is a singleton item that has a set of all possible specializations in a hospital |
Add new | / | pk: DOCTOR sk: SPECIALIZATION | Adding simply adds to the singleton's set | |
DoctorPatient | Assign Doctor to Patient | / | pk: DOCTOR#<DoctorId> sk: PATIENT#<PatientId> | Many-to-many rel for doctors and patients, uses GSI3 |
Remove patient from doctor | / | pk: DOCTOR#<DoctorId> sk: PATIENT#<PatientId> | / |
ENTITY | GSI1PK | GSI1SK |
---|---|---|
Doctor | DOCTOR#<DoctorId> | DOCTOR#<DoctorId> |
Test | DOCTOR#<DoctorId> | #TEST#<KSUID> |
Patient | PATIENT#<TRUNC(LastName)> | PATIENT#LAST_NAME)> |
ENTITY | GSI2PK | GSI2SK |
---|---|---|
Patient | PATIENT#<TRUNC(WEEK)> | PATIENT#CREATED_AT |
Doctor | SPECIALIZATION#<Specialization> | <Specialization>#<DoctorId> |
ENTITY | GSI3PK | GSI3SK |
---|---|---|
Patient | DOCTOR#<DoctorId> | PATIENT#<PatientId> |
Doctor | PATIENT#<PatientId> | DOCTOR#<DoctorId> |
- Move DynamoDB creds to .env
- [] Implement result pattern
- [] Export postman collection
- [] Add tests
- [] Add seed script
- [] Add API documentation
- [] Dockerize app w/ db