Week 8: Adding Search Functionality to Your FHIR Server
Michael Planchart
Healthcare Chief Architect and Data Engineer| Databricks | HL7, FHIR | AI/ML | NLP, NLU, BERT, T5, GPT, LLAMA
Welcome to Week 6 of the DIY FHIR Server Training Series. With CRUD operations implemented, your FHIR server is now capable of handling essential resource interactions. This week, we will focus on adding search functionality, enabling clients to query resources based on specific criteria. Search is a fundamental capability in FHIR, as it allows applications to retrieve subsets of data efficiently and flexibly.
By the end of this week, your FHIR server will support search parameters for the Patient resource, including searching by name, gender, and birth date.
Recap of Week 7 (TODO: Fix)
Last week, you implemented CRUD operations for the Patient resource, completing the foundational layer of resource management. These operations allow clients to create, retrieve, update, and delete patient data. If you need to revisit or enhance your CRUD implementation, now is a good time to do so before diving into search functionality.
Prerequisites
Before starting this chapter, ensure you have:
Detailed Topics for This Week
a. Understanding Search in FHIR
Search functionality in FHIR enables clients to query resources using parameters defined by the FHIR standard. For the Patient resource, some common search parameters include:
Search parameters are typically passed as query strings in the URL. For example:
GET /Patient?name=Smith\
GET /Patient?gender=male&birthdate=1980-01-01
FHIR servers are expected to handle these queries efficiently, returning only the resources that match the criteria.
b. Implementing Search for the Patient Resource
Let us build search functionality step by step.
1. Basic Search by Name
Add a new route to handle search queries using the name parameter.
Code Update: Search by Name
router.get('/', (req, res) => {
const { name } = req.query;
if (name) {
const matchingPatients = patients.filter(patient =>
patient.name.some(n =>
n.family.toLowerCase().includes(name.toLowerCase()) ||
n.given.some(g => g.toLowerCase().includes(name.toLowerCase()))
)
);
return res.json(matchingPatients);
}
res.json(patients); // Return all patients if no search parameter is provided
});
What’s New:
Test This:
2. Adding Gender and Birthdate Filters
Extend the search functionality to include gender and birthdate parameters.
领英推荐
Code Update: Search by Gender and Birthdate
router.get('/', (req, res) => {
const { name, gender, birthdate } = req.query;
let filteredPatients = patients;
if (name) {
filteredPatients = filteredPatients.filter(patient =>
patient.name.some(n =>
n.family.toLowerCase().includes(name.toLowerCase()) ||
n.given.some(g => g.toLowerCase().includes(name.toLowerCase()))
)
);
}
if (gender) {
filteredPatients = filteredPatients.filter(patient => patient.gender === gender.toLowerCase());
}
if (birthdate) {
filteredPatients = filteredPatients.filter(patient => patient.birthDate === birthdate);
}
res.json(filteredPatients);
});
What’s New:
Test This:
3. Handling No Matches
Ensure the API returns an appropriate response when no matches are found.
Code Update: Return 404 for No Matches
if (filteredPatients.length === 0) {
return res.status(404).json({ message: 'No patients found matching the criteria' });
}
c. Enhancing Code Modularity
Move the filtering logic to the patientService.js file for better maintainability.
Example: Refactored Service
function searchPatients(query) {
let { name, gender, birthdate } = query;
let filteredPatients = patients;
if (name) {
filteredPatients = filteredPatients.filter(patient =>
patient.name.some(n =>
n.family.toLowerCase().includes(name.toLowerCase()) ||
n.given.some(g => g.toLowerCase().includes(name.toLowerCase()))
)
);
}
if (gender) {
filteredPatients = filteredPatients.filter(patient => patient.gender === gender.toLowerCase());
}
if (birthdate) {
filteredPatients = filteredPatients.filter(patient => patient.birthDate === birthdate);
}
return filteredPatients;
}
module.exports = { searchPatients };
Fire Side Chats: Tips for Success
Takeaway Assignments
Add support for additional parameters, such as address or identifier.
Modify the search functionality to return paginated results using query parameters like count and offset.
Create test cases for the search functionality to ensure it handles different scenarios correctly.
Next Steps
After implementing basic search functionality this week, the next step is to expand your FHIR server’s query capabilities with advanced search features. In Week 9, you’ll build on the foundation of simple search parameters to include more powerful query options such as composite searches, token searches, and chained parameters. These features allow clients to perform more complex queries, such as searching for patients with a specific identifier or finding observations linked to a specific patient.
Additionally, you’ll implement _include and _revinclude parameters, enabling the retrieval of related resources in a single query. These advanced features make your FHIR server more versatile, allowing it to handle real-world use cases with greater efficiency and flexibility. Get ready to enhance your server's search functionality to meet the demands of modern healthcare systems!