Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tb 181 add mapping for probabilistic patient matching #257

Merged
merged 21 commits into from
Oct 31, 2023
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
17e45f3
Add mapping for cr-candidates endpoint
bradsawadye Oct 19, 2023
6a67d8c
Configure the candidate threshold by query
bradsawadye Oct 19, 2023
b3dc03a
Make the names more descriptive
bradsawadye Oct 19, 2023
131e1fd
Update the documentation
bradsawadye Oct 24, 2023
16b02c3
Merge branch 'main' into TB-181-add-mapping-for-cr-candidates
bradsawadye Oct 24, 2023
547a8d7
Adjust the endpoint for probabilistic patient matching
bradsawadye Oct 26, 2023
5c7fc03
Specify the type of error response
bradsawadye Oct 26, 2023
f578651
Update the documentation
bradsawadye Oct 26, 2023
b3fecce
Bump the version of the mapping mediator
bradsawadye Oct 26, 2023
671a997
Merge branch 'TB-181-add-mapping-for-cr-candidates' of github.com:jem…
bradsawadye Oct 26, 2023
e0b7a86
Change the pattern of the url for probabilistic matching
bradsawadye Oct 26, 2023
82fd280
Correct the probabilistic documentation
bradsawadye Oct 26, 2023
79c1c42
Respond in fhir format for lookup requests
bradsawadye Oct 26, 2023
a93edd5
Add validation for input for the probabilistic matching
bradsawadye Oct 26, 2023
29851d2
Fix validation logic
bradsawadye Oct 27, 2023
0ce21c8
Change the determinsitic endpint to a get request with the patient de…
bradsawadye Oct 27, 2023
afde022
Update the readme
bradsawadye Oct 27, 2023
4fb30cd
Correct the endponits' patterns
bradsawadye Oct 30, 2023
082a5e7
Create openhim channel for interacting with jempi
bradsawadye Oct 30, 2023
b25ca6f
Update the urls
bradsawadye Oct 30, 2023
6abcd3e
Change the search all logic so the response in not nested in an object
bradsawadye Oct 30, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 73 additions & 8 deletions client-registry-jempi/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ via the [mapping mediator](https://github.com/jembi/openhim-mediator-mapping) (i

POST http://localhost:3003/fhir/Patient

The `candidateThreshold` can optionally be set in the request query. The default value is 0.9

{
"resourceType": "Patient",
"gender": "male",
Expand Down Expand Up @@ -189,20 +191,83 @@ POST http://localhost:50000/JeMPI/cr-find
via the [mapping mediator](https://github.com/jembi/openhim-mediator-mapping) (in fhir format)

```sh
POST http://localhost:3003/fhir/Patients
GET http://localhost:3003/fhir/Patient/$exact

Query parameters - family, given, telecom, identifier, gender, birthDate, address (city)
```

## Query patients probabilistic

via the api (in JeMPI format)

```sh
POST - http://localhost:50000/JeMPI/cr-find

{
"operand": {
"fn": "match",
"name": "givenName",
"value": "drake",
"distance": 2
},
"operands": [
{
"operator": "and",
"operand": {
"fn": "match",
"name": "familyName",
"value": "brake",
"distance": 2
}
}
]
}
```

via the [mapping mediator](https://github.com/jembi/openhim-mediator-mapping) (in fhir format)

```sh

POST http://localhost:3003/fhir/Patient/$match

{
"resourceType": "Parameters",
"parameters": [
"parameter": [
{
"name": "and", // matches to the operator (options are "and" and "or")
"valueCode": "familyName", // matches to the field name (options are "givenName", "familyName", "dob", "nationalId", "gender", "city" and "phoneNumber")
"valueString": "creexxxeead" // matches to value of the field
"name": "givenName",
"valueString": "drake",
"part": [
{
"name": "operator",
"valueString": "and"
},
{
"name": "fn",
"valueString": "match"
},
{
"name": "distance",
"valueInteger": 2
}
]
},
{
"name": "and",
"valueCode": "city",
"valueString": "Indianapeeolis"
"name": "familyName",
"valueString": "brake",
"part": [
{
"name": "operator",
"valueString": "and"
},
{
"name": "fn",
"valueString": "match"
},
{
"name": "distance",
"valueInteger": 2
}
]
}
]
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ services:
target: /searchAll.json
- source: mediator-config-searchAllResponse.json
target: /searchAllResponse.json
- source: mediator-config-searchAllProbabilistic.json
target: /searchAllProbabilistic.json
- source: mediator-config-searchAllProbabilisticResponse.json
target: /searchAllProbabilisticResponse.json
networks:
mapping-mediator:
# This command will only attempt to import the config when the uptime responds with a 2xx
Expand Down Expand Up @@ -69,6 +73,16 @@ configs:
name: mediator-config-searchAllResponse.json-${mediator_config_searchAllResponse_json_DIGEST:?err}
labels:
name: jempi
mediator-config-searchAllProbabilistic.json:
file: ./searchAllProbabilistic.json
name: mediator-config-searchAllProbabilistic.json-${mediator_config_searchAllProbabilistic_json_DIGEST:?err}
labels:
name: jempi
mediator-config-searchAllProbabilisticResponse.json:
file: ./searchAllProbabilisticResponse.json
name: mediator-config-searchAllProbabilisticResponse.json-${mediator_config_searchAllProbabilisticResponse_json_DIGEST:?err}
labels:
name: jempi

networks:
mapping-mediator:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
},
"inputTransforms": {
"currentDate": "$now()",
"candidateThreshold": "$exists(query.candidateThreshold) ? query.candidateThreshold : constants.candidateThreshold",
"sourcePatient": "$exists(requestBody.identifier) and $exists(requestBody.identifier[0]) and $exists(requestBody.identifier[0].value) ? {'patient': requestBody.identifier[0].value, 'facility': requestBody.identifier[0].system} : null",
"nationalId": "$exists(requestBody.identifier) and $exists(requestBody.identifier[0]) and $count($filter(requestBody.identifier, function($v) {$contains($v.system, 'NationalID')})) > 0 ? $filter(requestBody.identifier, function($v) {$contains($v.system, 'NationalID')})[0].value : null",
"name": "$exists(requestBody.name) and $exists(requestBody.name[0]) and $exists(requestBody.name[0].given[0]) ? requestBody.name[0].given[0] : null",
Expand All @@ -18,7 +19,7 @@
"phoneNumber": "$exists(requestBody.telecom) and $exists(requestBody.telecom[0]) ? requestBody.telecom[0].value : null"
},
"inputMapping": {
"constants.candidateThreshold": "candidateThreshold",
"transforms.candidateThreshold": "candidateThreshold",
"transforms.sourcePatient": "sourceId",
"transforms.nationalId": "demographicData.nationalId",
"transforms.familyName": "demographicData.familyName",
Expand Down
13 changes: 9 additions & 4 deletions client-registry-jempi/importer/mapping-mediator/register.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,16 @@
"headers": {
"contentType": "application/fhir+json"
},
"url": "http://openhim-mapping-mediator:3003/register-response"
"url": "http://openhim-mapping-mediator:3003/register-response",
"params": {
"query": {
"candidateThreshold": {
"path": "query.candidateThreshold"
}
}
}
},
"extract": {
"JeMPIResponse": "$.body"
}
"fhirResponse": true
}
]
}
Expand Down
26 changes: 7 additions & 19 deletions client-registry-jempi/importer/mapping-mediator/searchAll.json
Original file line number Diff line number Diff line change
@@ -1,41 +1,29 @@
{
"name": "Search Endpoint",
"name": "Search Endpoint deterministic",
"endpoint": {
"pattern": "/fhir/Patients",
"method": "POST"
"pattern": "/fhir/Patient/$exact",
"method": "GET"
},
"transformation": {
"input": "JSON",
"output": "JSON"
},
"constants": {
"resourceType": "Bundle",
"type": "searchset"
},
"inputTransforms": {
"total": "$count(lookupRequests.jempiSearchAll.data.goldenRecords)",
"entry": "$map(lookupRequests.jempiSearchAll.data.goldenRecords, function($v) {{'fullUrl': 'Patient/' & $v.goldenId, 'resource': {'resourceType': 'Patient','id': $v.goldenId,'name': {'given': [$v.demographicData.givenName],'family': $v.demographicData.familyName},'address': [{'city': $v.demographicData.city}],'birthDate': $v.demographicData.dob,'telecom': [{'value': $v.demographicData.phoneNumber,'system': 'phone'}],'identifier': [{'system': $v.sourceId.facility,'value': $v.sourceId.patient},{'system': 'NationalID','value': $v.demographicData.nationalId}],'gender': $v.demographicData.gender}}})"
"operands": "($transform := function($v) {[query.family ? {'operator': 'and', 'operand': {'fn': 'eq', 'name': 'familyName', 'value': query.family}},query.given ? {'operator': 'and', 'operand': {'fn': 'eq', 'name': 'givenName', 'value': query.given}},query.gender ? {'operator': 'and', 'operand': {'fn': 'eq', 'name': 'gender', 'value': query.gender}},query.birthDate ? {'operator': 'and', 'operand': {'fn': 'eq', 'name': 'dob', 'value': query.birthDate}},query.address ? {'operator': 'and', 'operand': {'fn': 'eq', 'name': 'city', 'value': query.address}},query.telecom ? {'operator': 'and', 'operand': {'fn': 'eq', 'name': 'phoneNumber', 'value': query.telecom}},query.identifier ? {'operator': 'and', 'operand': {'fn': 'eq', 'name': 'nationalId', 'value': query.identifier}}]};$transform(query))"
},
"inputMapping": {
"constants.resourceType": "resourceType",
"constants.type": "type",
"transforms.total": "total",
"transforms.entry": "entry"
"transforms.operands": "operands",
"transforms.operands[0].operand": "operand"
},
"requests": {
"lookup": [
"response": [
{
"id": "jempiSearchAll",
"forwardExistingRequestBody": true,
"config": {
"method": "post",
"headers": {
"contentType": "application/json"
},
"url": "http://openhim-mapping-mediator:3003/search-response"
},
"extract": {
"JeMPIResponse": "$.body"
}
}
]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{
"name": "Search Endpoint probabilistic",
"endpoint": {
"pattern": "/fhir/Patient/$match",
"method": "POST"
},
"transformation": {
"input": "JSON",
"output": "JSON"
},
"constants": {
"resourceType": "Bundle",
"type": "searchset"
},
"inputTransforms": {
"total": "$count(lookupRequests.jempiSearchAllProbabilistic.data.goldenRecords)",
"entry": "$map(lookupRequests.jempiSearchAllProbabilistic.data.goldenRecords, function($v) {{'fullUrl': 'Patient/' & $v.goldenId, 'resource': {'resourceType': 'Patient','id': $v.goldenId,'name': {'given': [$v.demographicData.givenName],'family': $v.demographicData.familyName},'address': [{'city': $v.demographicData.city}],'birthDate': $v.demographicData.dob,'telecom': [{'value': $v.demographicData.phoneNumber,'system': 'phone'}],'identifier': [{'system': $v.sourceId.facility,'value': $v.sourceId.patient},{'system': 'NationalID','value': $v.demographicData.nationalId}],'gender': $v.demographicData.gender}}})"
},
"inputMapping": {
"constants.resourceType": "resourceType",
"constants.type": "type",
"transforms.total": "total",
"transforms.entry": "entry"
},
"requests": {
"lookup": [
{
"id": "jempiSearchAllProbabilistic",
"forwardExistingRequestBody": true,
"config": {
"method": "post",
"headers": {
"contentType": "application/json"
},
"url": "http://openhim-mapping-mediator:3003/search-response-probabilistic"
},
"fhirResponse": true
}
]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
{
"name": "Search Response Endpoint deterministic",
"endpoint": {
"pattern": "/search-response-probabilistic",
"method": "POST"
},
"transformation": {
"input": "JSON",
"output": "JSON"
},
"inputValidation": {
"type": "object",
"properties": {
"requestBody": {
"type": "object",
"properties": {
"parameter": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"valueString": {
"type": "string"
},
"part": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"valueString": {
"type": "string"
},
"valueInteger": {
"type": "number"
}
},
"required": ["name"]
}
}
},
"required": ["name", "valueString", "part"]
},
"minItems": 1
}
},
"required": ["parameter"]
}
}
},
"inputTransforms": {
"operands": "$append([], $map(requestBody.parameter, function($v) {{'operator': $single($v.part, function($v) {$v.name = 'operator'}).valueString, 'operand': {'fn': $single($v.part, function($v) {$v.name = 'fn'}).valueString, 'distance': $single($v.part, function($v) {$v.name = 'distance'}).valueInteger, 'name': $v.name, 'value': $v.valueString}}}))"
},
"inputMapping": {
"transforms.operands": "operands",
"transforms.operands[0].operand": "operand"
},
"requests": {
"response": [
{
"id": "jempiSearchAllProbabilisticResponse",
"config": {
"method": "post",
"url": "http://jempi-api:50000/JeMPI/cr-find"
}
}
]
}
}
Loading