Stream: ibm
Topic: Custom Sort Parameters
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.
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?
Lee Surprenant (Mar 18 2022 at 12:44):
It looks like you are doing GET [base]?_sort=created-at
Lee Surprenant (Mar 18 2022 at 12:45):
but your search param is only defined for Basic
Lee Surprenant (Mar 18 2022 at 12:45):
so it should be GET [base]/Basic?_sort=created-at
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
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
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.
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": []
}
}
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.
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?
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
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.
Lee Surprenant (Mar 19 2022 at 18:23):
i think these would be my general recommendations:
- use the Basic endpoint instead of whole-system search
- if using SMART App Launch, use the
user/Basic.read
scope instead ofpatient/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:
- 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
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
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