FHIR Chat · Custom Sort Parameters · ibm

Stream: ibm

Topic: Custom Sort Parameters


view this post on Zulip Batuhan Bulut (Mar 18 2022 at 11:46):

Hello @Lee Surprenant ,

I have a custom resource created by extending Basic resource. I want to sort them by datetime, decreasing. There is no default fields that holds datetime data in Basic resource, only date, which is not enough. This is why i use an extension to implement createdAt field of type "instant". I have created a search parameter config and it's code is "created-at". I'm trying to sort by adding "_sort=-created-at" query but this leads error. The log output says this: "Undefined sort parameter. resourceType=[Resource] sortParmCode=[created-at]". Looks like it is not enough to define search parameter and I couldn't find any document about defining a new sort parameter. Is there a way to achieve my goal?

Thanks in advance.

view this post on Zulip Lee Surprenant (Mar 18 2022 at 12:44):

Hi Batuhan, resourceType=[Resource] looks a bit suspicious... are you trying a whole-system search or are you searching Basic resources?

view this post on Zulip Lee Surprenant (Mar 18 2022 at 12:44):

It looks like you are doing GET [base]?_sort=created-at

view this post on Zulip Lee Surprenant (Mar 18 2022 at 12:45):

but your search param is only defined for Basic

view this post on Zulip Lee Surprenant (Mar 18 2022 at 12:45):

so it should be GET [base]/Basic?_sort=created-at

view this post on Zulip Lee Surprenant (Mar 18 2022 at 12:45):

or if you want it scoped to just your custom resource type, add a &code=your-code in there

view this post on Zulip Lee Surprenant (Mar 18 2022 at 12:47):

finally, what are the semantics of created-at? if its just when the resource was created, then you should be using _lastUpdated. if its some other instant (like when some real-world entity was created) then your approach seems right

view this post on Zulip Batuhan Bulut (Mar 18 2022 at 13:35):

Actually I'm searching on Basic resources but like this: GET [base]/?_type=Basic&_profile=${this.PROFILE}&to=${id}&_count=${count}&_page=${page}&_sort=-created-at. Probably this is why it cannot resolve resourceType as Basic while logging. to here is another search parameter and it works fine.

Let me show you some of my search attempts.
GET [base]/Basic
Response:

{
    "resourceType": "Bundle",
    "id": "e2a9bbbf-08af-47cb-9730-584ffd0447c5",
    "type": "searchset",
    "total": 0,
    "link": [
        {
            "relation": "self",
            "url": "https://localhost:9443/fhir-server/api/v4/Basic?_count=10&_page=1"
        }
    ]
}

GET [base]/Basic?_profile=https://mydomain.com/fhir/R4/StructureDefinition/UserNotification&_sort=created-at
Response:

{
    "resourceType": "Bundle",
    "id": "bd76b098-8ef6-430d-984f-47e4fb6a4ce5",
    "type": "searchset",
    "total": 0,
    "link": [
        {
            "relation": "self",
            "url": "https://localhost:9443/fhir-server/api/v4/Basic?_count=10&_profile=https://mydomain.com/fhir/R4/StructureDefinition/UserNotification&_sort=created-at&_page=1"
        }
    ]
}

GET [base]/?_type=Basic&_profile=https://mydomain.com/fhir/R4/StructureDefinition/UserNotification&_sort=created-at
Response:

{
    "resourceType": "OperationOutcome",
    "id": "ac-12-0-3-b8e26aae-37cb-44b7-a0b9-3c820b1c9214",
    "issue": [
        {
            "severity": "fatal",
            "code": "invalid",
            "details": {
                "text": "Undefined sort parameter. resourceType=[Resource] sortParmCode=[created-at]"
            },
            "expression": [
                "<empty>"
            ]
        }
    ]
}

GET [base]/?_type=Basic&_profile=https://mydomain.com/fhir/R4/StructureDefinition/UserNotification
Response:

{
    "resourceType": "Bundle",
    "id": "99cca769-e38e-41e2-adfd-3a989c61955d",
    "type": "searchset",
    "total": 6,
    "link": [
        {
            "relation": "self",
            "url": "https://localhost:9443/fhir-server/api/v4/?_count=10&_profile=https://mydomain.com/fhir/R4/StructureDefinition/UserNotification&_type=Basic&_page=1"
        }
    ],
    "entry": [
        {
            "fullUrl": "https://localhost:9443/fhir-server/api/v4//Basic/notification-id-1",
            "resource": {
                "resourceType": "Basic",
                "id": "notification-id-1",
                "meta": {
                    "versionId": "1",
                    "lastUpdated": "2022-03-18T10:54:13.833583Z",
                    "profile": [
                        "https://mydomain.com/fhir/R4/StructureDefinition/UserNotification"
                    ]
                },
                "extension": [
                    {
                        "extension": [
                            {
                                "url": "createdAt",
                                "valueInstant": "2022-03-18T10:54:07.156Z"
                            },
                    }
                ],
            },
            "search": {
                "mode": "match",
                "score": 1
            }
        },
    ]
}

I have clipped some of the data from last response to make it smaller.

view this post on Zulip Batuhan Bulut (Mar 18 2022 at 13:39):

And here is my search parameter definition:

{
    "fullUrl": "https://mydomain.com/fhir/R4/SearchParameter/UserNotification-createdAt",
    "resource": {
        "resourceType": "SearchParameter",
        "id": "UserNotification-createdAt",
        "url": "https://mydomain.com/fhir/R4/SearchParameter/UserNotification-createdAt",
        "version": "4.0.0",
        "name": "createdAt",
        "status": "draft",
        "experimental": false,
        "date": "2022-03-15T22:37:54+11:00",
        "description": "UserNotification's createdAt field",
        "code": "created-at",
        "base": [
            "Basic"
        ],
        "type": "date",
        "xpathUsage": "normal",
        "xpath": "f:Basic/f:extension[@url='https://mydomain.com/fhir/R4/StructureDefinition/UserNotificationExtension']/f:extension[@url='createdAt']/f:valueInstant",
        "expression": "Basic.extension.where(url='https://mydomain.com/fhir/R4/StructureDefinition/UserNotificationExtension').extension.where(url='createdAt').value",
        "multipleOr": true,
        "multipleAnd": true,
        "modifier": []
    }
}

view this post on Zulip Batuhan Bulut (Mar 18 2022 at 13:49):

I didn't use lastUpdated field because hl7 documentation says it shall be updated with current time when the resource updated. I want a datetime field that prone to updates.

view this post on Zulip Batuhan Bulut (Mar 18 2022 at 14:57):

Lee Surprenant said:

Hi Batuhan, resourceType=[Resource] looks a bit suspicious... are you trying a whole-system search or are you searching Basic resources?

Since it's not giving me error but zero results when I do GET [base]/Basic?_sort=created-at, the problem is different then.

When i directly search on Basic resource, none of my resources found, zero result. But I can access individual resources with GET [base]/Basic/[id]. When i do whole-system search by restricting the types, GET [base]/?_type=Basic, it just finds my resources (total 21 entries). Isn't it inconsistent? Does it have anything to do with SMART on FHIR?

view this post on Zulip Lee Surprenant (Mar 19 2022 at 18:15):

Does it have anything to do with SMART on FHIR?

do you have fhir-smart in your userlib?
if so, that could definitely contribute to this... the "Basic" resource can be in the patient compartment and so the fhir-smart interceptor would change a search like GET [base]/Basic into a compartment search like GET [base]/Patient/[context-id]/Basic.
but that doesn't really explain why you wouldn't be able to sort on your custom search parameter

view this post on Zulip Lee Surprenant (Mar 19 2022 at 18:20):

for that one, its probably just a limitation of our whole-system search implementation. whole-system search with a _type parameter that has a single value is a bit wonky... we allow you to use search parameters that apply to just that resource type but (as you found) apparently we don't allow sort parameters that apply to just that resource type in this case. personally, I think that seems like a reasonable limitation, but feel free to open an enhancement request.

view this post on Zulip Lee Surprenant (Mar 19 2022 at 18:23):

i think these would be my general recommendations:

  1. use the Basic endpoint instead of whole-system search
  2. if using SMART App Launch, use the user/Basic.read scope instead of patient/Basic.read

but, with that said, I still don't think our current fhir-smart implementation would support this because it doesn't know that your special Basic resource should be searchable to all users (i.e. is not bound to any patient compartment). therefor, I'm thinking your best bet would be to also do this:

  1. create your own persistence interceptor (probably starting with fhir-smart as your base) and make it do what you want

if you do number 3 and it feels generally applicable, feel free to open an issue to discuss your proposed changes

view this post on Zulip Lee Surprenant (Mar 19 2022 at 18:46):

for example, I could imagine modifying fhir-smart so that it does a normal search (instead of scoping the search to the compartment) when user/ scopes have been granted. or possibly make that configurable or something

view this post on Zulip Lee Surprenant (Mar 22 2022 at 13:11):

https://github.com/IBM/FHIR/issues/3495 <- @Batuhan Bulut interested for your feedback on this


Last updated: Apr 12 2022 at 19:14 UTC