# FHIR Questionnaire $extract This is a working space for discussing the various extract techniques defined by the FHIR SDC specification https://jira.hl7.org/browse/FHIR-37344 ## Issues I'd like to resolve: * Selecting the resource type to be able to select a profile * Permit multiple contexts * How to select to update an existing resource in the output transaction bundle * Populate values in the extracted resource without profile or hidden items * How to link resources output in the bundle (and still support create mode) * Define what `fullUrl` value to use in the bundle * If we are going to target merge style updates * How the process *could* update a resource via the transaction bundle * Should provenance resources be included in the bundle * *If they aren't in the bundle, the transaction processor has no idea where they came from to associate back to the QR.* Issues I don't think we can resolve: * Adding contained resources in resources in the bundle *(without profile slicing - even then I'm not convinced it's possible)* ### Selecting the resource by profile This can be achieved by permitting the use of canonical in the existing extension questionnaire-itemExtractionContext. Though I believe that this would require the binding to the resource type to be dropped. > **Note:** I'd also like to see the expression type removed from this, and remove that part of the extension definition, and have that done elsewhere, keeping the extension simple as just "what type of resource/profile of the resource is to be created/updated" - additional notes below. > **Note:** This is prototyped and working with my extract engine to permit easier review. ### Permit multiple contexts Remove from the specification the text: > *Note that only one context can be in play at the same time. When a new context is declared, it takes the place of the old context.* Maybe replace with something like: > As all `item.definition` values contain the resource profile canonical URL as a prefix and property, extracting to multiple resources can be mixed in a questionnaire's items. > While processing an itemExtractionContext, only the child items that have the exact canonical prefix matching the itemExtractionContext will be included in that resource. Items for other resource contexts will be ignored while processing that context. > **Note:** This is prototyped and working with my extract engine to permit easier review. > **Note:** You cannot "interleave" the same profile to extract data to different resources. ### Selecting a resource to update > **Background:** To make a resource by updated in a transaction bundle, the `entry.resource.id` is required be populated, and the `entry.request.method` to be `PUT`. > https://hl7.org/fhir/http.html#transaction The existing specification itemExtractionContext expression based extension should perform this action, however if that returns no value, there is no way to be able to tell what resource type is intended to be created. To achieve this I would recommend adding a new extension `questionnaire-itemExtractionUpdateResourceId` on a hidden string item in the questionnaire that contains the resource id. This value could be pre-populated during $prepopulate, or using calculated expression. The extension's value will be the `definition` of the resource's id. e.g. `http://hl7.org/fhir/StructureDefinition/Patient#Patient.id` The existence of an answer to this question would drive setting the `PUT` value in `entry.request.method`, otherwise a `POST` would be used. The alternative here is that just having the resource id set in the extracted resource is all that is needed to imply that this is an update rather than insert. > **Recommend:** Also suggest that the patient.meta.versionId should also indicate the version > Or alternately use entry.request.ifMatch (Patient/example/_history/34) may or may not have the server base URL prefix > **Note:** I don't think this can be a merge, and would have fun trying to pass the resource(s) to the $export operation to be processed in the function (as it may not have access to the server) ### Populate dynamic/calculated values in extract (without hidden fields) Propose a new complex extension `sdc-questionnaire-itemExtractionValue` to be able to provide values for an extracted property without requiring hidden items (and unnecessary data polluting the QR for extract). The extension will contain: | Name | Type | Description | | - | - | - | | `definition` | `canonical` | The profile prefixed property field (same as `item.definition`) | | `fixed-value` | *any* | Explicit value to put into the property. This is very useful for things like Coding/CodeableConcept that are not practical to create in fhirpath expressions | | `expression` | `Expression` | A fhirpath expression is used to evaluate the result to populate the property. If no value is returned from the expression, then the property is not populated. | This will be evaluated for each answer to the item after the value has been added to the extracted resource. If the definition is to a property that is a child of the item in context, then it should walk up the stack till it encounters an ancestor in common, and populate the field from that point. e.g. If the item.definition is on `...identifier.value` and the itemExtractionValue extension is on `...identifier.system`, then it would populate the system value for the same identifier and not create a new one. The fhirpath expression will have access to the following: * `context` - the item in the QR * `answer` - the specific answer on the item that is being processed? *(I haven't added this one, has no meaning for groups)* * `index` - the index of the `answer` in the current QR item answers collection *(I haven't added this one either - could be used to generate unique IDs to use)* * variable `item` - the item definition from the questionnaire * `questionnaire` - the questionnaire definition itself * `resource` - the QuestionnaireResponse > **Note:** This will not have access to other run-time evaluation level variables such as launchContexts or regular variables defined in the questionnaire. This is due to the evaluation not likely being evaluated in the same environment/time as the data entry of the form, and thus this information is not available. Ensure that all required data for this is in the questionnaire response, such as subject, encounter, source, auther etc. > **Note:** This is prototyped and working with my extract engine to permit easier review. ### Linking resources in the bundle Where the resource IDs are already known due to an update, or client allocated IDs, this is already possible with the dynamic values, though this doesn't work for server side ID allocation, as that uses the fullUrl and uuid creation. A new string extension `itemExtractionFullUrl` would be used to set the `entry.fullUrl`. It's value should be of the form `urn:uuid:...`, unclear if this should be a fhirpath expression or not to permit creating different values for iterations. It should be on the same item that has the itemExtractionContext extension. Then this value could be used in reference properties that need to link to that resource once it is created. Also refer to this link with additional details on the bundle entry fullUrl. https://hl7.org/fhir/bundle.html#bundle-unique > **Question:** Should we also permit setting other properties in the bundle.entry.request? > An alternative to this extension could be similar to the `sdc-questionnaire-itemExtractionValue` extension proposed above that instead has uses the definition propertie for the bundle. e.g. http://hl7.org/fhir/StructureDefinition/Bundle#Bundle.entry.request.ifNoneMatch > Or just a set of other extensions specifically for these props. --- ## Rough Pseudocode * scan entire `Questionnaire` resource for presence of `questionnaire-itemExtractionContext` extensions (at root or any item) * locate all answers for these items (which could be at the root or various groups) * create a resource instance of the type specified * if the type is a profile, add that to the meta * If there is an `itemExtractionFullUrl` extension on the item, set that in the resources entry in the bundle generated * Scan all the descendant items in the response with definition properties based on the itemExtractionContext canonical URL * For each answer to the item * set the property in the definition, if it is a collection, add a new item then add to that. This could be multiple levels deep, and same rules apply. * If the property is in a slice, also set all fixed/pattern values from the profile * If a definition is a backbone element and is on a group, then the type of the backbone element will be created, and child items will use this as their context to populate into (provided they are also descendants of this backbone element). If the element is a collection, then the new instance will be added to the collection. * Process any itemExtractionValue extensions to set additional data relative to this extracted item value. --- ## Some samples demonstrating some of the above *(and a draft of part of the content for my next blog post...)* #### Selecting the profiled resource to create/update My demonstration implementation is currently using a modification to the itemExtractionContext to support declaring the profile to extract to. ```json= { "extension": [ { "url": "http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-itemExtractionContext", "valueString": "http://hl7.org.nz/fhir/StructureDefinition/NzPatient" } ], "linkId": "assessment.demographics", "text": "demographics", "type": "group", ... } ``` #### Example identifier slice usage Assuming that we've declared that we're going to create an NzPatient profiled Patient resource, here's a sample item to capture the NZ National Patient Identifier: ```json= { "linkId": "nz-nhi", "definition": "http://hl7.org.nz/fhir/StructureDefinition/NzPatient#Patient.identifier:NHI.value", "text": "nhi", "type": "string" }, ``` Test this out with my [tester](https://dev.fhirpath-lab.com/Questionnaire/tester?tab=extract,csiro%20renderer&id=https%3A%2F%2Ffhir.forms-lab.com%2FQuestionnaire%2Fextract-defn-walkthrough-10&models=https%3A%2F%2Fhapi.fhir.org%2FbaseR4%2FStructureDefinition%3Furl%3Dhttp%3A%2F%2Fhl7.org.nz%2Ffhir%2FStructureDefinition%2FNzPatient,http%3A%2F%2Fhl7.org.nz%2Ffhir%2FStructureDefinition%2Fdhb), noting that if you want to use your own profiles, you'll need to provide them on the models tab. This definition was able to produce this identifier in the extracted resource: ```json= "identifier": [ { "use": "official", "system": "https://standards.digital.health.nz/ns/nhi-id", "value": "N12344" } ], ``` > **Explanation:** The NzPatient profile contains a slice on identifier named `NHI` that contains fixed values for the use and system. Hence these 2 values were also populated in the instance, along with the value from the answer. If there is no answer to the question, then the identifier would not be added. > *You can see the profile in the models page in the lab (which is how the tester was able to use the profile)* #### Example extension usage As extensions are just slices on profiles, using them is the same as we did above in the identifier example. ```json= { "linkId": "nz-dhb", "definition": "http://hl7.org.nz/fhir/StructureDefinition/NzPatient#Patient.extension:dhb.valueCodeableConcept.text", "text": "District Health Board", "type": "string" }, ``` Note that this approach removes the need to have the extension URL in the definition, and just uses the simpler slice name in the item definition. It does need to specify the `type` suffix on the item to ensure the correct type is created. *(Need to check this)* Test this out with my [tester](https://dev.fhirpath-lab.com/Questionnaire/tester?tab=extract,csiro%20renderer&id=https%3A%2F%2Ffhir.forms-lab.com%2FQuestionnaire%2Fextract-defn-walkthrough-10&models=https%3A%2F%2Fhapi.fhir.org%2FbaseR4%2FStructureDefinition%3Furl%3Dhttp%3A%2F%2Fhl7.org.nz%2Ffhir%2FStructureDefinition%2FNzPatient,http%3A%2F%2Fhl7.org.nz%2Ffhir%2FStructureDefinition%2Fdhb), noting that if you want to use your own profiles, you'll need to provide them on the models tab. ### Using fixed-value expression to create an extension (without a resource profile!) Since we can create any property, and then use the proposed definition expression approach to populate sibling data... ```json= { "linkId": "Q5", "definition": "http://hl7.org/fhir/StructureDefinition/Patient#Patient.birthDate.extension.value", "text": "What time were you born?", "type": "dateTime", "extension": [ { "extension": [ { "url": "definition", "valueCanonical": "http://hl7.org/fhir/StructureDefinition/Patient#Patient.birthDate.extension.url" }, { "url": "fixed-value", "valueExpression": "http://hl7.org/fhir/StructureDefinition/patient-birthTime" } ], "url": "http://hl7.org/fhir/StructureDefinition/sdc-questionnaire-itemExtractionValue" } ], }, ```