Using the HL7 FHIR® Da Vinci Health Record Exchange $member-match operation in IBM FHIR Server

HL7 FHIR® Da Vinci Health Record Exchange (HREX) is an FHIR Implementation Guide at version 0.2.0 – STU R1 – 2nd ballot. The HREX Implementation Guide is a foundational guide for all of the Da Vinci guides which support US payer, provider, member and HIPAA covered entity data exchange. The guide defines "FHIR profiles, operations" and depends on HL7 FHIR® US Core Implementation Guide STU3 Release 3.1.0. In an issue, I implemented this profile and operation.

As members (Patient) move from one plan (Coverage) to another plan (Coverage) or provider (Provider). To faciliates this exchange across boundaries, HREX introduces the $member-match operation which allows one health plan to retrieve a unique identifier for a member from another health plan using a member’s demographic and coverage information. This identifier can then be used to perform subsequent queries and operations. Members implementing a deterministic match require a match on member id or subscriber id at a minimum.

The IBM FHIR Server team has implemented the HREX Implementation Guide and Operation as two modules: fhir-ig-davinci-hrex HREX 0.2.0 Implementation Guide and fhir-operation-member-match. The operation depends on fhir-ig-us-core US Core 3.1.1. Note, in the main branch the fhir-ig-us-core supports 3.1.1 and 4.0.0. These three modules are to be released to Maven Central when the next version is tagged.

The $member-match operation executes on the Resource Type – Patient/$member-match. The operation implements the IBM FHIR Server Extended Operation framework using the Java Service Loader.

operation-framework

The $member-match provides a default strategy to execute strategy executes a series of Searches on the local FHIR Server to find a Patient on the system with a Patient and Coverage (to-match). The strategy is extensible by extending the strategy.

MemberMatch Framework

If the default strategy is not used, the Java Service Loader must be used by the new strategy. To register a JAR, META-INF/services/com.ibm.fhir.operation.davinci.hrex.provider.strategy.MemberMatchStrategy the file must point to the package and class that implements MemberMatchStrategy. Alternatively, AbstractMemberMatch or DefaultMemberMatchStrategy may be used as a starting point.

For implementers, there is an existing AbstractMemberMatch which provides a template and series of hooks to extend:

MemberMatchResult implements a light-weight response which gets translated to Output Parameters or OperationOutcomes if there is no match or multiple matches.

More advanced processing of the input and validation is shown in DefaultMemberMatchStrategy which processes the input resources to generate SearchParameter values to query the local IBM FHIR Server.

It’s highly recommended to extend the default implementation and override the getMemberMatchIdentifier for the strategy:

The $member-match operation is configured for each tenant using the respective fhir-server-config.json. The configuration is rooted under the path fhirServer/operations/membermatch.

Name Default Description
enabled true Enables or Disable the MemberMatch operation for the tenant
strategy default The key used to identify the MemberMatchStrategy that is loaded using the Java Service Loader
extendedProps true Used by custom MemberMatchStrategy implementations
{
    "__comment": "",
    "fhirServer": {
        "operations": {
            "membermatch": {
                "enabled": true,
                "strategy": "default",
                "extendedProps": {
                    "a": "b"
                }
            }
        }
    }
}

Recipe

  1. Prior to 4.10.0, build the Maven Projects and the Docker Build. You should see [INFO] BUILD SUCCESS after each Maven build, and docker.io/ibmcom/ibm-fhir-server:latest when the Docker build is successful.
mvn clean install -f fhir-examples -B -DskipTests -ntp
mvn clean install -f fhir-parent -B -DskipTests -ntp
docker build -t ibmcom/ibm-fhir-server:latest fhir-install
  1. Create a temporary directory for the dependencies that we’ll mount to userlib/, so it looks at:
userlib\
    fhir-ig-us-core-4.10.0.jar
    fhir-ig-davinci-hrex-4.10.0.jar
    fhir-operation-member-match-4.10.0.jar
export WORKSPACE=~/git/wffh/2021/fhir
mkdir -p ${WORKSPACE}/tmp/userlib
cp -p conformance/fhir-ig-davinci-hrex/target/fhir-ig-davinci-hrex-4.10.0-SNAPSHOT.jar ${WORKSPACE}/tmp/userlib/
cp -p conformance/fhir-ig-us-core/target/fhir-ig-us-core-4.10.0-SNAPSHOT.jar ${WORKSPACE}/tmp/userlib/
cp -p operation/fhir-operation-member-match/target/fhir-operation-member-match-4.10.0-SNAPSHOT.jar ${WORKSPACE}/tmp/userlib/

Note, the use of snapshot as these are not yet released.

  1. Download the fhir-server-config.json.
curl -L -o fhir-server-config.json \
    https://raw.githubusercontent.com/IBM/FHIR/main/fhir-server/liberty-config/config/default/fhir-server-config.json
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  8423  100  8423    0     0  40495      0 --:--:-- --:--:-- --:--:-- 40301
  1. Start the Docker container, and capture the container id. It’s going to take a few moments to start up as it lays down the test database.
docker run -d -p 9443:9443 -e BOOTSTRAP_DB=true \
  -v $(pwd)/fhir-server-config.json:/config/config/default/fhir-server-config.json \
  -v ${WORKSPACE}/tmp/userlib:/config/userlib/ \
  ibmcom/ibm-fhir-server:latest
4334334a3a6ad395c4b600e14c8563d7b8a652de1d3fdf14bc8aad9e6682cc02
  1. Check the logs until you see:
docker logs 4334334a3a6ad395c4b600e14c8563d7b8a652de1d3fdf14bc8aad9e6682cc02
...
[6/16/21, 15:31:34:533 UTC] 0000002a FeatureManage A   CWWKF0011I: The defaultServer server is ready to run a smarter planet. The defaultServer server started in 17.665 seconds.
  1. Download and update the Sample Data
curl -L 'https://raw.githubusercontent.com/IBM/FHIR/main/conformance/fhir-ig-davinci-hrex/src/test/resources/JSON/020/Parameters-member-match-in.json' \
-o Parameters-member-match-in.json
  1. Split the resource out from the sample:
cat Parameters-member-match-in.json | jq -r '.parameter[0].resource' > Patient.json
cat Parameters-member-match-in.json | jq -r '.parameter[1].resource' > Coverage.json
  1. Load the Sample Data bundle to the IBM FHIR Server
curl -k --location --request PUT 'https://localhost:9443/fhir-server/api/v4/Patient/1' \
--header 'Content-Type: application/fhir+json' \
--header 'Prefer: return=representation' \
--user "fhiruser:${DUMMY_PASSWORD}" \
--data-binary  "@Patient.json"

curl -k --location --request PUT 'https://localhost:9443/fhir-server/api/v4/Coverage/9876B1' \
--header 'Content-Type: application/fhir+json' \
--header 'Prefer: return=representation' \
--user "fhiruser:${DUMMY_PASSWORD}" \
--data-binary  "@Coverage.json"

Note, DUMMY_PASSWORD should be previously set to your server’s password.

  1. Execute the Member Match
curl -k --location --request POST 'https://localhost:9443/fhir-server/api/v4/Patient/$member-match' \
--header 'Content-Type: application/fhir+json' \
--header 'Prefer: return=representation' \
--user "fhiruser:${DUMMY_PASSWORD}" \
--data-binary  "@Parameters-member-match-in.json" -o response.json

When you execute the operation, it runs two visitors across the Parameters input to generate searches against the persistence store:

  • DefaultMemberMatchStrategy.MemberMatchPatientSearchCompiler – Enables the Processing of a Patient Resource into a MultivaluedMap, which is subsequently used for the Search Operation. Note there are no SearchParameters for us-core-race, us-core-ethnicity, us-core-birthsex these elements in the US Core Patient profile. The following fields are combined in a Search for the Patient:

      - Patient.identifier
      - Patient.name
      - Patient.telecom
      - Patient.gender
      - Patient.birthDate
      - Patient.address
      - Patient.communication
    
  • DefaultMemberMatchStrategy.MemberMatchCovergeSearchCompiler Coverage is a bit unique here. It’s the CoverageToMatch – details of prior health plan coverage provided by the member, typically from their health plan coverage card and has dubious provenance. The following fields are combined in a Search for the Coverage.

      - Coverage.identifier
      - Coverage.beneficiary
      - Coverage.payor
      - Coverage.subscriber
      - Coverage.subscriberId
    

Best wishes with MemberMatch.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.