Week 6: Implementing CRUD Operations for FHIR Resources
Michael Planchart
Healthcare Chief Architect and Data Engineer| Databricks | HL7, FHIR | AI/ML | NLP, NLU, BERT, T5, GPT, LLAMA
Congratulations! You’ve reached a significant milestone, 25% of the course is complete. Your dedication to building a FHIR server has brought you through foundational concepts, architectural planning, and developing your first FHIR endpoints. This week, we’ll take it a step further by implementing CRUD operations (Create, Read, Update, Delete) for FHIR resources, enabling full interaction with the Patient resource.
Mastering CRUD operations is essential for any server, as it forms the backbone of how resources are managed and exchanged in real-world systems. By the end of this week, your FHIR server will be capable of handling end-to-end operations for managing patient data.
Recap of Week 5
In Week 5, we explored how to ensure data integrity by validating FHIR resources using Python. You learned to leverage the fhir.resources library to check compliance with FHIR standards and implemented custom Python scripts to detect errors and enforce additional validation rules. These skills help ensure that only well-formed and compliant resources are processed by your server.
By the end of the week, you had a working validation script capable of handling individual resources or batches, providing a crucial layer of quality assurance for your FHIR server. This validation process is essential for maintaining interoperability and avoiding downstream errors.
Prerequisites
Before starting this chapter, ensure you have:
Detailed Topics for This Week
a. Expanding CRUD Functionality for the Patient Resource
CRUD operations are the foundation for resource management in FHIR. Let’s implement them one by one.
1. Create (POST)
You already implemented a basic POST method for creating patients. Let’s enhance it by adding input validation and error handling.
Code Update: Adding Validation
router.post('/', (req, res) => {
const { id, name } = req.body;
if (!id || !name) {
return res.status(400).json({ error: 'Missing required fields: id, name' });
}
const newPatient = req.body;
patients.push(newPatient);
res.status(201).json(newPatient);
});
What’s New:
2. Read (GET)
You already implemented a GET method to retrieve all patients. Let’s now add the ability to fetch a specific patient by their id.
Code Update: Retrieve Patient by ID
router.get('/:id', (req, res) => {
const patient = patients.find(p => p.id === req.params.id);
if (!patient) {
return res.status(404).json({ error: 'Patient not found' });
}
res.json(patient);
});
What’s New:
Test This:
3. Update (PUT)
Updating an existing resource is key to maintaining up-to-date data.
Code Update: Update Patient by ID
router.put('/:id', (req, res) => {
const patientIndex = patients.findIndex(p => p.id === req.params.id);
if (patientIndex === -1) {
return res.status(404).json({ error: 'Patient not found' });
}
const updatedPatient = { ...patients[patientIndex], ...req.body };
patients[patientIndex] = updatedPatient;
res.json(updatedPatient);
});
What’s New:
领英推荐
Test This:
4. Delete (DELETE)
Deleting a resource is necessary for managing outdated or erroneous data.
Code Update: Delete Patient by ID
router.delete('/:id', (req, res) => {
const patientIndex = patients.findIndex(p => p.id === req.params.id);
if (patientIndex === -1) {
return res.status(404).json({ error: 'Patient not found' });
}
patients.splice(patientIndex, 1);
res.status(204).send();
});
What’s New:
Test This:
b. Enhancing Code Modularity
To keep your code organized as it grows:
Example: Refactored patientService.js
let patients = [];
function getAllPatients() {
return patients;
}
function getPatientById(id) {
return patients.find(p => p.id === id);
}
function addPatient(patient) {
patients.push(patient);
}
function updatePatient(id, updatedData) {
const patientIndex = patients.findIndex(p => p.id === id);
if (patientIndex === -1) return null;
patients[patientIndex] = { ...patients[patientIndex], ...updatedData };
return patients[patientIndex];
}
function deletePatient(id) {
const patientIndex = patients.findIndex(p => p.id === id);
if (patientIndex === -1) return null;
patients.splice(patientIndex, 1);
}
module.exports = { getAllPatients, getPatientById, addPatient, updatePatient, deletePatient };
Fire Side Chats: Tips for Success
Takeaway Assignments
Add more detailed validation, such as checking for duplicate IDs when creating a patient.
Use Postman or the REST Client extension to test all four CRUD operations thoroughly.
Integrate basic logging to track CRUD operations and improve traceability.
Next Steps
Next week, we will add search functionality to your FHIR server, enabling clients to query patient resources using parameters such as name or birth date. This will make your server even more versatile and closer to real-world applications.
Congratulations again on reaching this milestone, keep up the great work as you continue to build a robust FHIR server!