Week 7: Storing FHIR Resources in MongoDB
Michael Planchart
Healthcare Chief Architect and Data Engineer| Databricks | HL7, FHIR | AI/ML | NLP, NLU, BERT, T5, GPT, LLAMA
Welcome to Week 7 of the DIY FHIR Server Training Series. Now that you’ve built a functioning FHIR server with basic CRUD operations and validation, it’s time to focus on resource storage. In this chapter, we’ll introduce MongoDB, a NoSQL database that is well-suited for handling JSON-based data like FHIR resources. By the end of this week, you’ll have a fully integrated MongoDB setup to store FHIR resources efficiently, along with optimized queries and indexing for performance.
Recap of Week 6
In Week 6, you extended your FHIR server’s functionality by implementing full CRUD operations (Create, Read, Update, and Delete) for the Patient resource. These operations formed the backbone of resource management, allowing clients to dynamically interact with the server to add new resources, retrieve existing ones, make updates, and remove obsolete data.
By completing CRUD operations, your server is now capable of handling essential interactions with FHIR resources. This foundation sets the stage for Week 7, where you’ll focus on integrating MongoDB to store these resources efficiently and enable high-performance data handling.
Prerequisites
Before diving into MongoDB integration, ensure you have:
Download and install MongoDB from MongoDB’s official website.
Familiarity with MongoDB’s insertOne, find, updateOne, and deleteOne operations.
Install the official MongoDB Node.js driver:
npm install mongodb
Setting Up MongoDB for FHIR Resource Storage
1. Starting Your MongoDB Instance
Start the MongoDB service:
mongod
This launches the database server locally, typically accessible at mongodb://localhost:27017.
2. Designing a Database for FHIR Resources
For this tutorial:
3. Connecting Your FHIR Server to MongoDB
Add a connection utility to your project. Create a new file named dbConfig.js in the database folder:
const { MongoClient } = require('mongodb');
// MongoDB connection URI
const uri = 'mongodb://localhost:27017';
const client = new MongoClient(uri);
let database;
async function connectToDatabase() {
try {
await client.connect();
console.log('Connected to MongoDB');
database = client.db('fhir_server');
} catch (error) {
console.error('Error connecting to MongoDB:', error);
}
}
function getDatabase() {
if (!database) {
throw new Error('Database connection not established');
}
return database;
}
module.exports = { connectToDatabase, getDatabase };
Call the connectToDatabase function in your server's main.js or server.js file during initialization:
const { connectToDatabase } = require('./database/dbConfig');
(async () => {
await connectToDatabase();
app.listen(3000, () => {
console.log('Server is running on port 3000');
});
})();
Handling CRUD Operations with MongoDB
1. Creating a Patient
Update your POST handler to store resources in MongoDB:
领英推荐
const { getDatabase } = require('../database/dbConfig');
router.post('/', async (req, res) => {
try {
const patient = req.body;
const db = getDatabase();
const result = await db.collection('patients').insertOne(patient);
res.status(201).json({ id: result.insertedId, ...patient });
} catch (error) {
res.status(500).json({ error: 'Failed to store patient' });
}});
2. Retrieving Patients
Update the GET handler to retrieve patients from MongoDB:
router.get('/', async (req, res) => {
try {
const db = getDatabase();
const patients = await db.collection('patients').find().toArray();
res.json(patients);
} catch (error) {
res.status(500).json({ error: 'Failed to retrieve patients' });
}
});
3. Optimizing Queries with Indexing
Indexes improve query performance by allowing MongoDB to locate records faster. Create an index on the name.family field to speed up searches for patient names:
mongo
use fhir_server
db.patients.createIndex({ 'name.family': 1 })
4. Updating a Patient
Update the PUT handler to modify a patient’s record in MongoDB:
router.put('/:id', async (req, res) => {
try {
const db = getDatabase();
const id = req.params.id;
const updatedData = req.body;
const result = await db.collection('patients').updateOne(
{ _id: new MongoClient.ObjectId(id) },
{ $set: updatedData }
);
if (result.matchedCount === 0) {
return res.status(404).json({ error: 'Patient not found' });
}
res.json({ message: 'Patient updated successfully' });
} catch (error) {
res.status(500).json({ error: 'Failed to update patient' });
}
});
5. Deleting a Patient
Update the DELETE handler to remove a patient from MongoDB:
router.delete('/:id', async (req, res) => {
try {
const db = getDatabase();
const id = req.params.id;
const result = await db.collection('patients').deleteOne(
{ _id: new MongoClient.ObjectId(id) }
);
if (result.deletedCount === 0) {
return res.status(404).json({ error: 'Patient not found' });
}
res.status(204).send();
} catch (error) {
res.status(500).json({ error: 'Failed to delete patient' });
}
});
Fire Side Chats: Tips for Success
Takeaway Assignments
Add collections for Observation or Practitioner resources.
Experiment with indexed and non-indexed fields to see the impact on query performance.
Use MongoDB’s aggregation framework to analyze complex queries, such as fetching all patients with recent encounters.
Next Steps
With your FHIR resources now securely stored in MongoDB, the next step is to implement search functionality that allows clients to query these resources effectively. In Week 8, you’ll learn to add support for FHIR’s search parameters and query options, such as filtering patients by name, date of birth, or other attributes.
This functionality will make your FHIR server more dynamic and user-friendly, enabling efficient data retrieval and enhancing its real-world applicability. Get ready to dive into search capabilities, optimizing your server for flexible and powerful data queries!