Using Rhapsody as a FHIR® façade (Part Three)
In my previous blog, readers went through the exercise of mapping from the database to the resources that they are going to need. The scenario was simple (though it won’t always be this way) but there are still a few more items to cover:
- Resource ID
- Supported search parameters
Every resource has an ID element that uniquely and permanently identifies it on the server. In the spec it’s referred to as the ‘logical’ ID. There’s more information about the resource ID here and here . The Resource ID serves a number of purposes with a few important to us.
- Think of the resource ID as the ‘address’. For example, if a Patient resource has an ID of 100 and the base address of the server where it is stored is http:myServer/FHIR, then the following URL will always retrieve the resource (assuming a RESTful environment): http:myServer/FHIR/Patient/100. Note the resource type, ‘Patient’, is part of the address.
- The Resource ID is unique on the server, it is the mechanism by which references are made. For example, the Encounter resource needs to have a reference to the patient, and it uses the id of the patient to make that reference. See an XML example from my previous blog here.
- When creating each resource, there needs to be a way to locate/create an id. Exactly how this is done is not defined in FHIR – there may be a database field (or fields) that can be used – or the database primary key can be used (There may be risks if the database is modified – whether this is a concern will be implementation dependent). Be careful about using ‘business’ identifiers like a ‘Medical Record Number’ as they are generally not suitable for resource ids.
Supported search parameters:
Next to think about are the query parameters or searches that you are going to support. There are a lot of options, every resource has a set of pre-defined search parameters at the bottom of each resource page, for example see http://hl7.org/fhir/patient.html#search for Patient. Don’t assume that a search parameter is always the name of an element in the resource – for example Encounter.practitioner. You aren’t obliged to support all of them and can choose the ones you want, and even add your own. One exception is that you should support the resource read using the id as described above.
As well as simple searches – such as, find all patients with a surname of ‘smith’ – that return one or more instances of the same type of resource, there are more complex ones that ‘follow the references’ between resources when performing the query. For example, suppose we are searching for all the encounters for a patient. We have the patient identifier (the Medical Record Number) so there, at least, are a couple of ways we could support that search.
We could require the client to first find the Patient on our server, and that would give us the patient id. Next, they make a query on the Encounter resource to return the encounters. This query would look something like: http:myServer/FHIR/Encounter?patient=19477
Alternatively, we could decide to support chained queries – where we don’t need to find the patient first, we pass in a property of the Patient as part of the query. For example: http:myServer/FHIR/Encounter?patient.identifier=abc1234 would return all the Encounters where the encounters patient property had an identifier of abc1234. (Actually, we should also include the system of the identifier as well – I’m just being lazy here). The advantage of this approach is this it’s just a single query – the complexity has moved to the server. In the spec check out http://hl7.org/fhir/search.html#chaining for more details.
We can even get more complex in our queries, for example by using the following query http:myServer/FHIR/Encounter?patient.identifier=abc1234&_include=Encounter:patient
we return the matching encounters and the patient resource as well. So, deciding what search parameters to support is extremely important. Note that If we’re developing our interface to be compliant with an Implementation Guide (like Argonaut in the US or CareConnect in the UK) then the required searches might already be defined.
Finally let’s discuss the resource text element. This element is present in all resource types and it’s recommended that it should be present in all instances. (Think of the ‘type’ as a cookie cutter, and an ‘instance’ as a cookie from that cutter). It should be clinically safe to display the resource text to a user, so that they will understand what the resource represents.
For example, the Encounter test might have the patient name and date of birth, the encounter date and the practitioner. Exactly what is present in the text element is up to the server as there are no firm requirements in FHIR other than it being clinically safe. For more details see http://hl7.org/fhir/narrative.html.
It is significant that the text element also has a ‘status’ property which indicates how the text was derived. Given that you are exposing a proxy interface using an Integration Engine, you would likely use ‘generated’— or just exercise your right to leave the element out completely and set the status to ‘empty’. The value of using ‘empty’ is that you are explicit that there is no text, which can be appropriate in some circumstances.
We’re almost at the stage of actually starting to build our proxy but there are still a few things to discuss. For example, coded data can be challenging to supply yet it is so important for semantic interoperability, we should also mention security and privacy, and we should have a think about how we can be sure that we’re producing ‘correct’ FHIR resources and what our options are for validating what we are producing — all of which will be covered in future blogs.