Modelling Encounters with FHIR
January 24, 2014 Leave a comment
One of the tasks I’ve been given here at Orion is to look at our internal data stores, and see how we could create a FHIR based service layer that would allow external (and internal) consumers to interact with that store.
I started with the Encounter service, and things went pretty well – but I realized that if this was to make sense to other BA’s (Business Analysts) and Developers then I needed to draw the bigger picture – how the resources would relate to each other when representing an encounter – it’s not quite as simple as it might seem!
The biggest change in thinking is going to be thinking in terms of multiple resources. If we want to retrieve the details of a single encounter, then we’re not going to just call the service and get back a single object that represents the encounter and all the properties of that encounter – rather we’re going to get back an ‘object graph’ – a number of resources related to that encounter contained within an atom bundle.
The client could request that the server return the referenced resources by using the _include parameter to specify the resources that it would like to be included in the returned bundle. (It could also get back just the Encounter and then make separate calls for all the referenced resources – but that’s a bit klutzy, and there are other problems that we’ll talk about in a minute).
I’ve used the New Zealand situation for this discussion to demonstrate the process I used: the actual relationship of entities will be different in different realms of course (HL7 uses the term ‘realm’ to refer to different countries).
So, from the diagram we can see that:
- The hospital organization is part of a DHB (District Health Board)
- A primary care centre is in the catchment area of a hospital (this needed an extension).
- The hospital location has a number of ward locations
- An encounter at a hospital refers to the hospital Organization as the service provider, and has relationships within a number of wards within that hospital. It also has relationships with the patient and one or more participants
- A primary care encounter has exactly the same sort of relationships – albeit with different resource instances. (Just for fun, I associated the Primary Care Clinician with the hospital encounter to show that the GP was also involved in the patients care while in hospital. This is not uncommon in New Zealand – or at least it was when I practiced medicine a few decades ago…)
So what does this look like on the wire?
Well the snippet below shows a hospital encounter, with the resources within a bundle and appropriate references between resources for the (It’s not complete of course – in fact there’s just enough in there to allow it to validate).
<feed xmlns="http://www.w3.org/2005/Atom"> <title>Encounter Resource with all related Resources as separate resources</title> <id>urn:uuid:500bee81-d973-4afe-b592-d39fe71e38</id> <updated>2013-05-28T22:12:21Z</updated> <!-- Time the bundle was built --> <!-- Author is required by the Atom spec. FHIR doesn't use it--> <author> <name>Harold House Surgeon</name> </author> <entry> <title>Encounter Resource</title> <id>cid:encounter1</id> <updated>2013-05-28T22:12:21Z</updated> <content type="text/xml"> <Encounter xmlns="http://hl7.org/fhir"> <text> <status value="additional"/> <div xmlns="http://www.w3.org/1999/xhtml">An encounter at Ward 10 Middlemore hospital, for John Cardinal from 1st to 3rd January 2014. Dr Marcus Welby attending.</div> </text> <status value="finished"/> <class value="inpatient"/> <subject> <reference value="cid:patient"/> <display value="John Cardinal"/> </subject> <participant> <individual> <reference value="cid:doctor"/> <display value="Dr Marcus Welby"/> </individual> </participant> <period> <start value="2014-01-01"/> <end value="2014-01-03"/> </period> <location> <location> <reference value="cid:ward"/> <display value="Ward 10"/> </location> <period> <start value="2014-01-01"/> <end value="2014-01-03"/> </period> </location> <serviceProvider> <reference value="cid:hospital"/> </serviceProvider> </Encounter> </content> </entry> <entry> <title>Patient details</title> <id>cid:patient</id> <updated>2013-05-28T22:12:21Z</updated> <content type="text/xml"> <Patient xmlns="http://hl7.org/fhir"> <text> <status value="additional"/> <div xmlns="http://www.w3.org/1999/xhtml">John Cardinal</div> </text> </Patient> </content> </entry> <entry> <title>Hospital</title> <id>cid:hospital</id> <updated>2013-05-28T22:12:21Z</updated> <content type="text/xml"> <Organization xmlns="http://hl7.org/fhir"> <text> <status value="additional"/> <div xmlns="http://www.w3.org/1999/xhtml">Middlemore Hospital</div> </text> </Organization> </content> </entry> <entry> <title>Location (ward)</title> <id>cid:ward</id> <updated>2013-05-28T22:12:21Z</updated> <content type="text/xml"> <Location xmlns="http://hl7.org/fhir"> <text> <status value="additional"/> <div xmlns="http://www.w3.org/1999/xhtml">Ward 10</div> </text> </Location> </content> </entry> <entry> <title>Practitioner</title> <id>cid:doctor</id> <updated>2013-05-28T22:12:21Z</updated> <content type="text/xml"> <Practitioner xmlns="http://hl7.org/fhir"> <text> <status value="additional"/> <div xmlns="http://www.w3.org/1999/xhtml">Dr Marcus Welby</div> </text> </Practitioner> </content> </entry> </feed>
The query that would retrieve this bundle looks something like this:
GET [root]/Encounter?subject={patientID}&_include=Encounter.subject&_include=Encounter.Location...
Now there’s actually an issue with this representation, and it relates to our old friend the resource identity.
In this bundle all the resources are identified as ‘cid:’ references – meaning that they don’t refer to ‘real’ resources back on the server. (Because our back end is not fully FHIR enabled (yet), we’ve constructed the resources ‘on the fly’ from the data in the Encounter when the query was processed).
But what should the recipient do with the bundle if it wanted to save it locally? It would need to create a new resource locally for each one in the bundle. What would happen if the client made 2 separate queries for encounters, and each encounter referred to the same patient? The client would have no way of knowing this, and so would create another resource for the same patient.
So the more correct way to deal with this is to ‘contain’ the unidentified resources within the Encounter like this:
<feed xmlns="http://www.w3.org/2005/Atom"> <title>Encounter Resource with all related Resources as contained resources</title> <id>urn:uuid:500bee81-d973-4afe-b592-d39fe71e38</id> <updated>2013-05-28T22:12:21Z</updated> <!-- Time the bundle was built --> <entry> <title>Encounter Resource</title> <id>cid:enc1</id> <updated>2013-05-28T22:12:21Z</updated> <content type="text/xml"> <Encounter xmlns="http://hl7.org/fhir"> <text> <status value="generated"/> <div xmlns="http://www.w3.org/1999/xhtml">An encounter at Ward 10 Middlemore hospital, for John Cardinal from 1st to 3rd January 2014. Dr Marcus Welby attending.</div> </text> <contained> <Patient id="patient"> <name> <text value="John Cardinal"/> </name> </Patient> </contained> <contained> <Practitioner id="doctor"> <name> <text value="Dr Marcus Welby"/> </name> </Practitioner> </contained> <contained> <Location id="ward"> <name value="Ward 10"/> </Location> </contained> <contained> <Organization id="hospital"> <name value="Middlemore Hospital"/> </Organization> </contained> <status value="finished"/> <class value="inpatient"/> <subject> <reference value="#patient"/> <display value="John Cardinal"/> </subject> <participant> <individual> <reference value="#doctor"/> <display value="Dr Marcus Welby"/> </individual> </participant> <period> <start value="2014-01-01"/> <end value="2014-01-03"/> </period> <location> <location> <reference value="#ward"/> <display value="Ward 10"/> </location> <period> <start value="2014-01-01"/> <end value="2014-01-03"/> </period> </location> <serviceProvider> <reference value="#hospital"/> <display value="Middlemore Hospital"/> </serviceProvider> </Encounter> </content> </entry> </feed>
This makes it explicit to the recipient that the contained resources only have meaning within the context of the containing Encounter. (And note that the contained resources no longer have a <text> element – the spec discourages this).
As we progress with FHIR, we’ll be able to start to expose ‘real’ resources (with proper identities). For example, once we have a Patient resource endpoint available, then we won’t have to contain the Patient resource in the Encounter – it will be an ‘identifiable’ resource with a ‘real’ URL that points to it – and we can choose to include the resource in the bundle or not. This does mean that the representation will change over time with resources moving from being contained to being ‘real’ resources in their own right, but that’s something that comes with being a FHIR client.
Of course this interface is actually more complex than the one it replaced, and it will take more work server-side to produce it that the previous custom version did. Where there was a single ‘object’ representing the encounter, we now have an object graph. But – and it is an important but – our interface can be used by any FHIR compliant system, which means that we can support – and promote – an international ecosystem of health information exchange.
Further, much of the complexity can be hidden behind libraries that are freely available (or we can write our own if we want to). It’s clean and easy to understand. And, finally, we have a design than has been created by some of the smartest minds in healthcare IT – and it didn’t cost us anything!
What’s not to like?
Recent Comments