Plone powered provider for fhirpath
Project description
Background (collective.fhirpath)
fhirpath implementation in Plone, essential battery included, ready to use.
Installation
Install collective.fhirpath by adding it to your buildout:
[buildout] ... eggs += collective.fhirpath
and then running bin/buildout
From Plone controlpanel in the addon settings, install collective.fhirpath.
How It Works
``FhirResource`` the fhirfield
Make sure this specialized field is used properly according to plone.app.fhirfield documentation.
Make field indexable
A specilized Catalog PluginIndexes is named FhirFieldIndex is available, you will use it as like other catalog indexes.
Example:
<?xml version="1.0"?> <object name="portal_catalog" meta_type="Plone Catalog Tool"> <index name="organization_resource" meta_type="FhirFieldIndex"> <indexed_attr value="organization_resource"/> </index> </object>
Elasticsearch settings
Make sure elasticsearch has been configured accourding to collective.elasticsearch docs.
Usages
- FHIR Search::
>>> from fhirpath.interfaces import IElasticsearchEngineFactory >>> from fhirpath.interfaces import IFhirSearch >>> from fhirpath.interfaces import ISearchContextFactory >>> from plone import api >>> from collective.elasticsearch.es import ElasticSearchCatalog >>> from zope.component import queryMultiAdapter
>>> es_catalog = ElasticSearchCatalog(api.portal.get_tool("portal_catalog")) >>> factory = queryMultiAdapter( .... (es_catalog,), IElasticsearchEngineFactory .... ) >>> engine = factory(fhir_release="STU3") >>> search_context = queryMultiAdapter((engine,), ISearchContextFactory)( .... resource_type, unrestricted=False) >>> search_factory = queryMultiAdapter((search_context,), IFhirSearch)
>>> params = ( .... ("_profile", "http://hl7.org/fhir/Organization"), .... ("identifier", "urn:oid:2.16.528.1|91654"), .... ("type", "http://hl7.org/fhir/organization-type|prov"), .... ("address-postalcode", "9100 AA"), .... ("address", "Den Burg"), .... ) >>> bundle = search_factory(params) >>> len(bundle.entry) 2 >>> # with query string. >>> # query_string = self.request["QUERY_STRING] >>> query_string = "_profile=http://hl7.org/fhir/Organization&identifier=urn:oid:2.16.528.1|91654&type=http://hl7.org/fhir/organization-type|prov&address-postalcode=9100+AA" >>> bundle = search_factory(query_string=query_string) >>> len(bundle.entry) 2
- ZCatlog FHIR Search::
>>> from collective.fhirpath.interfaces import IZCatalogFhirSearch >>> zcatalog_factory = queryMultiAdapter((search_context,), IZCatalogFhirSearch)
>>> # with query string. >>> # query_string = self.request["QUERY_STRING] >>> query_string = "_profile=http://hl7.org/fhir/Organization&identifier=urn:oid:2.16.528.1|91654&type=http://hl7.org/fhir/organization-type|prov&address-postalcode=9100+AA" >>> brains = zcatalog_factory(query_string=query_string) >>> len(brains) 2
- FHIR Query::
>>> from fhirpath.interfaces import IElasticsearchEngineFactory >>> from fhirpath.interfaces import IFhirSearch >>> from fhirpath.interfaces import ISearchContextFactory >>> from plone import api >>> from collective.elasticsearch.es import ElasticSearchCatalog >>> from zope.component import queryMultiAdapter >>> from fhirpath.query import Q_ >>> from fhirpath.fql import T_ >>> from fhirpath.fql import sort_ >>> from fhirpath.enums import SortOrderType
>>> es_catalog = ElasticSearchCatalog(api.portal.get_tool("portal_catalog")) >>> factory = queryMultiAdapter( .... (es_catalog,), IElasticsearchEngineFactory .... ) >>> engine = factory(fhir_release="STU3") >>> query_builder = Q_(resource="Organization", engine=engine) .... query_builder = query_builder.where( .... T_("Organization.meta.profile", "http://hl7.org/fhir/Organization") .... ).sort(sort_("Organization.meta.lastUpdated", SortOrderType.DESC))
>>> result = query_builder(async_result=False, unrestricted=True).fetchall() >>> result.header.total 2 >>> query_result = query_builder(async_result=False, unrestricted=True) >>> for resource in query_result: .... count += 1 .... assert resource.__class__.__name__ == "Organization"
>>> query_builder = Q_(resource="Organization", engine=engine) >>> query_builder = query_builder.where(T_("Organization.id", "f001")) >>> result_query = query_builder(async_result=False, unrestricted=True) >>> resource = result_query.single() >>> resource is not None True
>>> query_builder = Q_(resource="Organization", engine=engine) >>> query_builder = query_builder.where( .... T_("Organization.meta.profile", "http://hl7.org/fhir/Organization") .... ) >>> result_query = builder(async_result=False, unrestricted=True) >>> result = result_query.first() >>> isinstance(result, result_query._query.get_from()[0][1]) True
Use FHIRModelServiceMixin
For better performance optimization, you should use FHIRModelServiceMixin to response FHIRModel, FhirFieldValue object efficiently.
Example 1:
>>> from plone.restapi.services import Service >>> from collective.fhirpath.utils import FHIRModelServiceMixin >>> class MyFHIRGetService(FHIRModelServiceMixin, Service): .... """ """ .... def reply(self): .... # do return bellow's types of data .... # could be ``dict`` type data .... # could be instance of ``FHIRAbstractModel`` derrived class. .... # could be instance of ``plone.app.fhirfield.FhirResourceValue`` derrived class. .... # or self.reply_no_content()
configuration
This product provides three plone registry based records fhirpath.es.index.mapping.nested_fields.limit, fhirpath.es.index.mapping.depth.limit, fhirpath.es.index.mapping.total_fields.limit. Those are related to ElasticSearch index mapping setup, if you aware about it, then you have option to modify from plone control panel (Registry).
Documentation
Full documentation for end users can be found in the “docs” folder, and is also available online at https://collective-fhirpath.readthedocs.io/
Contribute
Issue Tracker: https://github.com/nazrulworld/collective.fhirpath/issues
Source Code: https://github.com/nazrulworld/collective.fhirpath
Documentation: https://collective-fhirpath.readthedocs.io/
Support
If you are having issues, please let us know at: Md Nazrul Islam<email2nazrul@gmail.com>
License
The project is licensed under the GPLv2.
REST Client Examples
Getting single resource, here we are getting Patient resource by ID.
Example(1):
>>> response = admin_session.get('/@fhir/Patient/19c5245f-89a8-49f8-b244-666b32adb92e') >>> response.status_code 200 <BLANKLINE> >>> response.json()['resourceType'] == 'Patient' True <BLANKLINE> >>> response = admin_session.get('/@fhir/Patient/19c5245f-fake-id') >>> response.status_code 404 <BLANKLINE>
Search Observation by Patient reference with status condition. Any observation until December 2017 and earlier than January 2017.
Example(2):
>>> response = admin_session.get('/@fhir/Observation?patient=Patient/19c5245f-89a8-49f8-b244-666b32adb92e&status=final&_lastUpdated=lt2017-12-31T00%3A00%3A00%2B00%3A00&_lastUpdated=gt2017-01-01T00%3A00%3A00%2B00%3A00') >>> response.status_code 200 >>> response.json()["total"] 1 <BLANKLINE>
Add FHIR Resource through REST API
Example(3):
>>> import os >>> import json >>> import uuid >>> import DateTime >>> import time >>> with open(os.path.join(FIXTURE_PATH, 'Patient.json'), 'r') as f: ... fhir_json = json.load(f) >>> fhir_json['id'] = str(uuid.uuid4()) >>> fhir_json['name'][0]['text'] = 'Another Patient' >>> response = admin_session.post('/@fhir/Patient', json=fhir_json) >>> response.status_code 201 >>> time.sleep(1) >>> response = admin_session.get('/@fhir/Patient?active=true') >>> response.json()["total"] 2
Update (PATCH) FHIR Resource the Patient is currently activated, we will deactive.
Example(4):
>>> patch = [{'op': 'replace', 'path': '/active', 'value': False}] >>> response = admin_session.patch('/@fhir/Patient/19c5245f-89a8-49f8-b244-666b32adb92e', json={'patch': patch}) >>> response.status_code 204 <BLANKLINE>
Contributors
Md Nazrul Islam, email2nazrul@gmail.com (author)
Changelog
0.8.0 (2022-06-13)
New features
A patch has been added in response to issue#91 on collective.elasticsearch.
0.7.6 (2021-05-04)
minimum fhir.resources version is now 6.1.0 and minimum collective.elasticsearch version is now 3.0.5
0.7.5 (2020-12-17)
minimum fhir.resources version is now 6.0.0, see it’s associated changes at https://pypi-hypernode.com/project/fhir.resources/6.0.0/.
minimum fhirpath``version is now ``0.10.5, see it’s associated improvements and bug fixes at https://pypi-hypernode.com/project/fhirpath/0.10.4/
minimum plone.app.fhirfield``version is now ``4.2.0, see it’s associated improvements and bug fixes at https://pypi-hypernode.com/project/plone.app.fhirfield/4.2.0/
0.7.4 (2020-11-19)
Minimum required fhirpath version is now 0.10.4 (see it’s changes log) and added compabilities.
0.7.3 (2020-10-24)
new helper function json_body has been created, which is using orjson deserializer.
FHIRModelServiceMixin is now more performance optimized.
0.7.2 (2020-10-06)
Bundle resposne as dict option enable in ZCatalog based search.
0.7.1 (2020-10-05)
fhirpath``minimum version has been updated, which includes minimum ``fhir.resources version 6.0.0b5.
Improvements for FHIRModelServiceMixin as orjson serializer used.
0.7.0 (2020-09-25)
Improvements
Issue #2 ZCatalog based search should have option to return bundle type alongside as LazyBrain
Supports all features from fhirpath 0.8.0.
Elasticsearch Mappings JSON files are updated.
Fixes
utils.FHIRModelServiceMixin can now handle list type data in response.
0.6.1 (2020-09-09)
plone.app.fhirfield:default``has been added in dependency, so no need separete install of ``plone.app.fhirfield.
0.6.0 (2020-09-09)
Improvements
FHIRModelServiceMixin class has been available under utils module, which can be used with your plone.restapi services to response type as FhirModel aka pydantic’s BaseModel or plone.app.fhirfield.FhirFieldValue object with the best possible effecient way.
0.5.0 (2020-08-18)
Improvements
Supports the revolutionary version of fhir.resources via fhirpath we may expect some refactor on your existing codebase because of some breaking changes, please see changes at fhir.resources, plone.app.fhirfield and fhirpath.
Brings back support for Python version 3.6
Three configurations (fhirpath.es.index.mapping.nested_fields.limit, fhirpath.es.index.mapping.depth.limit, fhirpath.es.index.mapping.total_fields.limit) based on plone registry has now been available.
0.4.0 (2020-05-15)
Breakings
As a part of supporting latest fhirpath version (from 0.6.1), drop python version later than 3.7.0.
ElasticsearchEngineFactory.__call__’s argument name fhir_version changed to fhir_release.
0.3.0 (2019-11-10)
Improvements
ZCatalog featured fhir search added, from which you will get ZCatalog´s brain feature.
FhirFieldIndex named PluginIndex is now available.
FHIR STU3``and ``R4 search mapping is now available.
Others improvements that make able to use in production project (of course without guarantee.)
0.2.0 (2019-09-16)
first working versions, with lots of improvements.
0.1.0 (2019-09-06)
Initial release. [nazrulworld]
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Hashes for collective.fhirpath-0.8.0.tar.gz
Algorithm | Hash digest | |
---|---|---|
SHA256 | d58b20f440774b8de287b6ea6d7b13d973822b022977aaf795844b489a4100bf |
|
MD5 | f63313f6e4a707907213356d6509f5d0 |
|
BLAKE2b-256 | 1a96ef8bab4177fbb5306473aaf46585506d1631e830be7fe9b03bf925759f89 |
Hashes for collective.fhirpath-0.8.0-py2.py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | c1116eba802d866c5a67ae4e457a1199dd7188ff1efd2e7f4b97fb8c5c0dc103 |
|
MD5 | b2a49682679f75ed9669d0734e5417ff |
|
BLAKE2b-256 | 304297b93a00d08f1fd84e46d2addf4b169b2e9f234b578cf9ac460cc335aea9 |