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

feat: adds new feature Fhir.es_sql() #217

Merged
merged 2 commits into from
Mar 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
19 changes: 19 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

_(NOTE: All examples use fictitious data or freely available data sets.)_

## [0.34.0] - 2024-03-13

### Added

- A New function `es_sql()` to `phc.services.Fhir` class to execute OpenSearch SQL.

Example:

```python
df = Fhir(session).es_sql(
project_id='xxx',
statement='SELECT id, subject.reference FROM diagnostic_report WHERE identifier.system = ? LIMIT 10',
params=[{
"type": "string",
"value": "example-identifier-system"
}]
).get_as_dataframe('datarows')
```

## [0.33.4] - 2023-11-02

### Fixed
Expand Down
5 changes: 5 additions & 0 deletions phc/api_response.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,11 @@ def get_as_dataframe(
mapped = list(map(mapFunc, self.data.get(key)))
return _pd.DataFrame(mapped)

# support OpenSearch sql response
if key == "datarows" and self.data.get("schema") is not None:
column_names = [col["name"] for col in self.data.get("schema")]
return _pd.DataFrame(self.data.get(key), columns=column_names)

return _pd.DataFrame(self.data.get(key))

def validate(self):
Expand Down
37 changes: 35 additions & 2 deletions phc/services/fhir.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

from phc.base_client import BaseClient
from phc import ApiResponse
from typing import List, Dict


class Fhir(BaseClient):
Expand Down Expand Up @@ -64,7 +65,7 @@ def sql(self, project: str, statement: str, scroll="") -> ApiResponse:
def execute_sql(
self, project_id: str, statement: str, scroll=""
) -> ApiResponse:
"""Executes an SQL query against fhir-searh-service
"""Executes an SQL query against fhir-search-service

Parameters
----------
Expand Down Expand Up @@ -106,7 +107,7 @@ def execute_sql(
def execute_es(
self, project_id: str, query: dict, scroll=""
) -> ApiResponse:
"""Executes an elasticsearch query against fhir-searh-service
"""Executes an elasticsearch query against fhir-search-service

Parameters
----------
Expand All @@ -127,3 +128,35 @@ def execute_es(
json=query,
params={"scroll": scroll},
)

def es_sql(
self,
project_id: str,
statement: str,
params: List[Dict],
subject_id="",
) -> ApiResponse:
"""Executes an OpenSearch SQL against fhir-search-service

Parameters
----------
project_id : str
The project ID
statement : str
The prepared OpenSearch SQL statement
params: List[Dict]

Returns
-------
phc.ApiResponse
The query response
"""
api_path = f"fhir-search/sql/projects/{project_id}"
if subject_id is not None and subject_id != "":
api_path = f"{api_path}/patients/{subject_id}"

return self._api_call(
api_path=api_path,
http_verb="POST",
json={"query": statement, "parameters": params},
)
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "phc"
version = "0.33.4"
version = "0.34.0"
description = "Python SDK for the LifeOmic platform"
authors = ["LifeOmic <development@lifeomic.com>"]
license = "MIT"
Expand Down
32 changes: 32 additions & 0 deletions tests/test_fhir_opensearch_sql.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
from phc import Session
import os
from phc.services import Fhir
from unittest.mock import patch
from test_session import jwt, sample


@patch("phc.base_client.BaseClient._api_call")
def test_es_sql(mock_api_call):
session = Session(token=jwt.encode(sample, "secret"), account="bar")
fhir = Fhir(session)
project_id = "bar"
query = "SELECT id, subject FROM diagnostic_report WHERE identifier.system = ? LIMIT 10"
params = [
{
"type": "string",
"value": "lrn:lo:dev:fountainlife:ehr:fountainlife:d22c690b-fb45-4ff2-8cb3-eed9f665cb30/DiagnosticReport",
}
]

res = fhir.es_sql(
project_id=project_id,
statement=query,
params=params,
)

mock_api_call.assert_called_once()
args, kwargs = mock_api_call.call_args

assert kwargs["api_path"] == f"fhir-search/sql/projects/{project_id}"
assert kwargs["json"]["query"] == query
assert kwargs["json"]["parameters"] == params
Loading