Package: collective.fhirpath
Background (collective.fhirpath)fhirpathimplementation in Plone, essential battery included, ready to use.InstallationInstall collective.fhirpath by adding it to your buildout:[buildout]
...
eggs +=
    collective.fhirpathand then runningbin/buildoutFrom Plone controlpanel in the addon settings, installcollective.fhirpath.How It Works``FhirResource`` the fhirfieldMake sure this specialized field is used properly according toplone.app.fhirfielddocumentation.Make field indexableA specilized Catalog PluginIndexes is namedFhirFieldIndexis 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 settingsMake sure elasticsearch has been configured accourding tocollective.elasticsearchdocs.UsagesFHIR 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)
2ZCatlog 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)
2FHIR 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])
TrueUseFHIRModelServiceMixinFor better performance optimization, you should useFHIRModelServiceMixinto responseFHIRModel,FhirFieldValueobject 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()configurationThis product provides three plone registry based recordsfhirpath.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).DocumentationFull documentation for end users can be found in the “docs” folder,
and is also available online athttps://collective-fhirpath.readthedocs.io/ContributeIssue Tracker:https://github.com/nazrulworld/collective.fhirpath/issuesSource Code:https://github.com/nazrulworld/collective.fhirpathDocumentation:https://collective-fhirpath.readthedocs.io/SupportIf you are having issues, please let us know at: Md Nazrul Islam<email2nazrul@gmail.com>LicenseThe project is licensed under the GPLv2.REST Client ExamplesGetting 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 APIExample(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"]
2Update (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>ContributorsMd Nazrul Islam,email2nazrul@gmail.com(author)Changelog0.8.0 (2022-06-13)New featuresA patch has been added in response toissue#91oncollective.elasticsearch.0.7.6 (2021-05-04)minimumfhir.resourcesversion is now6.1.0and minimumcollective.elasticsearchversion is now3.0.50.7.5 (2020-12-17)minimumfhir.resourcesversion is now6.0.0, see it’s associated changes athttps://pypi.org/project/fhir.resources/6.0.0/.minimumfhirpath``versionis now ``0.10.5, see it’s associated improvements and bug fixes athttps://pypi.org/project/fhirpath/0.10.4/minimumplone.app.fhirfield``versionis now ``4.2.0, see it’s associated improvements and bug fixes athttps://pypi.org/project/plone.app.fhirfield/4.2.0/0.7.4 (2020-11-19)Minimum requiredfhirpathversion is now0.10.4(see it’s changes log) and added compabilities.0.7.3 (2020-10-24)new helper functionjson_bodyhas been created, which is usingorjsondeserializer.FHIRModelServiceMixinis now more performance optimized.0.7.2 (2020-10-06)Bundle resposne asdictoption enable in ZCatalog based search.0.7.1 (2020-10-05)fhirpath``minimumversion has been updated, which includes minimum ``fhir.resourcesversion6.0.0b5.Improvements forFHIRModelServiceMixinas orjson serializer used.0.7.0 (2020-09-25)ImprovementsIssue #2ZCatalog based search should have option to return bundle type alongside as LazyBrainSupports all features fromfhirpath0.8.0.Elasticsearch Mappings JSON files are updated.Fixesutils.FHIRModelServiceMixincan now handlelisttype data in response.0.6.1 (2020-09-09)plone.app.fhirfield:default``hasbeen added in dependency, so no need separete install of ``plone.app.fhirfield.0.6.0 (2020-09-09)ImprovementsFHIRModelServiceMixinclass has been available underutilsmodule, which can be used with yourplone.restapiservices to response type asFhirModelaka pydantic’sBaseModelorplone.app.fhirfield.FhirFieldValueobject with the best possible effecient way.0.5.0 (2020-08-18)ImprovementsSupports the revolutionary version offhir.resourcesviafhirpathwe may expect some refactor on your existing codebase because of some breaking changes, please see changes atfhir.resources,plone.app.fhirfieldandfhirpath.Brings back support for Python version 3.6Three 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)BreakingsAs a part of supporting latestfhirpathversion (from0.6.1), drop python version later than3.7.0.ElasticsearchEngineFactory.__call__’s argument namefhir_versionchanged tofhir_release.0.3.0 (2019-11-10)ImprovementsZCatalog featured fhir search added, from which you will get ZCatalog´s brain feature.FhirFieldIndexnamed PluginIndex is now available.FHIRSTU3``and``R4search 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]