IHTSDO / snowstorm

Scalable SNOMED CT Terminology Server using Elasticsearch
Other
208 stars 83 forks source link

Deltas using the FHIR api #176

Open Tannjorn opened 4 years ago

Tannjorn commented 4 years ago

We have been trying to find out how to pull deltas using the FHIR APIs. Our attempted string is something like this: http://test.terminologi.ehelse.no/fhir/ValueSet/$expand?url=http://snomed.info/sct?fhir_vs=ecl/<<90332006&count=10&_lastUpdated=gt20200131

But regardless of what date I put in, it seems to return the same result. Any input appreciated.

pgwilliams commented 4 years ago

Hi Tannjorn, great to hear from you.

The main blocker here is that we've not yet added support for the _lastUpdated parameter on any resource. It has been discussed, but an issue that needs to be answered is that SNOMED CT does versioning at the level of individual components, where FHIR thinks at the level of codes - or concepts as we call them. So if you were to say > 20200131 would you just want new/updated changes to the concept items, or would you also consider relationships and descriptions changing? And where would you draw the line - changes to dialect acceptability, changes to historical associations etc. So the last time it was discussed, we were coming down on the side of just considering the date as it's stated for the concept object itself.

I'm very interested to know what your use case is , because Deltas are very much a SNOMED CT RF2 thing, and FHIR - being terminology agnostic - doesn't know about such SNOMED specific detail.

I see you're using Snowstorm. If we needed a delta here we would normally export that using the native Snowstorm "Export" endpoint. But I'd be happy to discuss further because obviously that _lastUpdated parameter is part of the specification and we should add support for it.

danka74 commented 4 years ago

https://www.hl7.org/fhir/search.html#lastUpdated seems to return the instances changed since that date. My interpretation is that it would include the ValueSet definition rather than any expansion, but perhaps this needs clarification. "The search parameter _lastUpdated can be used to select resources based on the last time they were changed:" Also, from reading the spec, it seems to return the instance in its entirety, not only the delta. So, some clarification might be needed, but I don't think this parameter can be used to create a DELTA.

Tannjorn commented 4 years ago

Hi @pgwilliams, And thanks for your swift reply.

My use-case is related to medicines. We are trying to build a national extension to support substance based prescribing, using SNOMED core, expanding content to meet requirements of our current masterdata and creating a map from brands (outside SNOMED) to Clinical Drug (in SNOMED).

Sadly our users (the health and care sector) finds it too "difficult" to adapt to Snowstorm. The proposed solution is that we create all content in SNOMED (using Managed Services), mirror this to a production-load Snowstorm. One Snowstorm for the official release, and one QA-server for the DailyBuild. Further our National Medicines Authority (NOMA) will have their own SQL-based environment, aiming at an information structure compatible with IDMP.

At first all hospitals have said they will only be able to read the SQL-based API-service. (Not that I understand why, but seem to be under the misconception that everything needs to be a "single table").

But here lies the reason for my question: NOMA wants to query Snowstorm for updated content, and mirror this into their SQL-environment. They will call the APIs and build three object, one for MP, one for MPF and one for CD. Then tie these together using SCTIDs as key for relationships. First pull from Snowstorm is thought to be a Snapshot, then they would like to do incremental loads to update content - hence the need for a DELTA.

Hope this description helps to explain the use case. Could it be an idea to use valid date? Search for all content with a valid date after the last search?

There is of course a possibility to use Snowstorm Native REST, but we still have a hypothesis that getting them on the FHIR API is a better solution for the future.

lawley commented 4 years ago

The problem is that _lastUpdated is a parameter for FHIR Search.

You are not doing a Search (which would look like .../ValueSet?url=...&_lastUpdated=... or .../ValueSet/_search?url=...&_lastUpdated=...), but rather invoking the $expand operation.

However, if you want a delta of new codes between version A and version B of SNOMED (or any CodeSystem) then you can do so with an explicit ValueSet like the following that does a delta between SNOMED CT-AU 20201031 and 20190930 for the same ECL expression you have above.

{
  "resourceType": "ValueSet",
  "text": {
    "status": "generated",
    "div": "<div xmlns=\"http://www.w3.org/1999/xhtml\"><h2>SNOMED Delta example</h2><tt>http://csiro.au/snomed-delta-example</tt></div>"
  },
  "url": "http://csiro.au/snomed-delta-example",
  "title": "SNOMED Delta example",
  "name": "SNOMED_Delta_example",
  "status": "draft",
  "compose": {
    "include": [{
        "system": "http://snomed.info/sct",
        "version": "http://snomed.info/sct/32506021000036107/version/20201031",
        "filter": [{
            "property": "constraint",
            "op": "=",
            "value": "<<90332006"
        }]
    }],
    "exclude": [{
        "system": "http://snomed.info/sct",
        "version": "http://snomed.info/sct/32506021000036107/version/20190930",
        "filter": [{
            "property": "constraint",
            "op": "=",
            "value": "<<90332006"
        }]
    }]
  }
}
lawley commented 3 years ago

@pgwilliams Snowstorm doesn't like the above, but does work with non-standard version values like "32506021000036107/version/20190930"

pgwilliams commented 3 years ago

@lawley that is an ingenious solution for obtaining a delta in a ValueSet. I'll try to get that working in Snowstorm and also tighten up the rules on the version field so that the proper URI format is enforced. Thank you!

@Tannjorn The above solution will only pick up new Medicinal Product concepts, not changes to terms or attributes. So it's not a true Delta.

I hesitate to suggest this because it's a backwards step in terms of technology, but if your client is wedded to a MySQL solution then loading SNOMED into MySQL tables remains an option. See https://github.com/IHTSDO/snomed-database-loader/tree/master/MySQL

mertenssander commented 3 years ago

Adding to this, I got a question regarding the detection of concepts that get removed from a refset. It appears that this inverse also works. This would be the corresponding call to $expand:

{
    "resourceType": "Parameters",
    "parameter": [
        {
            "name": "valueSet",
            "resource": {
                "resourceType": "ValueSet",
                "compose": {
                    "include": [
                        {
                            "system": "http://snomed.info/sct",
                            "version": "http://snomed.info/sct/11000146104/version/20200331",
                            "filter": [
                                {
                                    "property": "concept",
                                    "op": "in",
                                    "value": "723264001"
                                }
                            ]
                        }
                    ],
                    "exclude": [
                        {
                            "system": "http://snomed.info/sct",
                            "version": "http://snomed.info/sct/11000146104/version/20200930",
                            "filter": [
                                {
                                    "property": "concept",
                                    "op": "in",
                                    "value": "723264001"
                                }
                            ]
                        }
                    ]
                }
            }
        }
    ]
}