Stream: implementers
Topic: Transaction conditional create OR update
Sean McIlvenna (Sep 04 2018 at 17:45):
How do you tell a transaction to do a conditional create OR update?
Sean McIlvenna (Sep 04 2018 at 17:45):
i.e. if the resource doesn't exist with the criteria, create it. if the resource does exist with the criteria, update it instead
Lloyd McKenzie (Sep 04 2018 at 17:49):
You'd list the resource twice. We should probably make explicit that failure to meet conditional create/update requirements doesn't get treated as a failure within a transaction.
Sean McIlvenna (Sep 04 2018 at 17:50):
so, one entry in the transaction with POST (conditional create), and another entry with PUT (conditional update)
Stefan Lang (Sep 04 2018 at 17:51):
What you describe, is actually a conditional update:
"
No matches: The server performs a create interaction
One Match: The server performs the update against the matching resource
"
Sean McIlvenna (Sep 04 2018 at 17:51):
that works.. but makes for a VERY large bundle if doing this to many resources
Stefan Lang (Sep 04 2018 at 17:51):
https://www.hl7.org/fhir/http.html#cond-update
Stefan Lang (Sep 04 2018 at 17:52):
No need to have it twice, if I read you correct
Lloyd McKenzie (Sep 04 2018 at 17:52):
@Stefan Lang That's only true if you want the client to assign the id on a create. I was assuming @Sean McIlvenna wanted server-assigned create ids.
Sean McIlvenna (Sep 04 2018 at 17:52):
ok, @Stefan Lang , I'll give that a shot
Sean McIlvenna (Sep 04 2018 at 17:52):
thx
Stefan Lang (Sep 04 2018 at 17:55):
@Lloyd McKenzie Where is that stated? isn't a create a create and as such should ignore any id sent from the client?
Stefan Lang (Sep 04 2018 at 18:02):
https://build.fhir.org/http.html#cond-update explicitely says:
"The resource MAY contain an id element, but does not need to (this is one of the few cases where a resource exists without an id element). If an id is provided, the server SHALL ignore it - see documentation for the update interaction. "
Lloyd McKenzie (Sep 04 2018 at 18:13):
That section says: "No matches: The server treats the interaction as an Update as Create interaction (or rejects it, if it does not support Update as Create)". Update as Create means client-assigned id. The part about not having an id is presumably because the id is conveyed in the URL.
Sean McIlvenna (Sep 04 2018 at 18:19):
So... not sure how I would do a conditional update without an ID, though
Sean McIlvenna (Sep 04 2018 at 18:20):
for example, if I have a CapabilityStatement that does NOT have an ID, but I want to conditionally create/update the resource on the FHIR server based on the CapabilityStatement.url...
Sean McIlvenna (Sep 04 2018 at 18:20):
what would I put for the METHOD/URL of the request?
Sean McIlvenna (Sep 04 2018 at 18:21):
I couldn't use "PUT" because PUT would require a URL like .../CapabilityStatement/<id>
Sean McIlvenna (Sep 04 2018 at 18:21):
I would have to use POST with .../CapabilityStatement as the url
Stefan Lang (Sep 04 2018 at 18:21):
Right, the "No matches" definition has changed between STU3 and current build.
The new definition looks rather inconsistent to me, since at the the top it states "without id", but "Update as Create" talks about ids
Sean McIlvenna (Sep 04 2018 at 18:21):
I think...
Sean McIlvenna (Sep 04 2018 at 18:21):
would be great to have a set of bullets in guidance for various scenarios, and what to do...
Sean McIlvenna (Sep 04 2018 at 18:22):
ultimately I'm just trying to setup "import" for end-users... I don't know if the resource already exists on the server, and I don't know if the user is sending a resource with an id or not
Sean McIlvenna (Sep 04 2018 at 18:23):
but I know that for some resources, I can use .url as a canonical id to find out if it exists already
Stefan Lang (Sep 04 2018 at 18:24):
@Sean McIlvenna a conditional update means "without id, but with search criteria". But I admit the new definition leaves me a bit confused
Stefan Lang (Sep 04 2018 at 18:50):
@Lloyd McKenzie If the client would not send an id (whereever), this should still work a a regular create, right?
Sean McIlvenna (Sep 04 2018 at 19:07):
yah... I'm now completely confused as-to how I should construct this "create or update" transaction for multiple resources
Lloyd McKenzie (Sep 04 2018 at 19:07):
I'm not clear on that. @Grahame Grieve @Josh Mandel ?
Stefan Lang (Sep 04 2018 at 19:29):
How else would one perform a "STU3 way" of conditional update?
Stefan Lang (Sep 04 2018 at 21:04):
I.e. the original primary use case:
- I don't know the id and not even, whether that resource exists
- but I have enough information to define criteria that hopefully represent a unique key
- and I don't care about the id that resource already has or will get
Grahame Grieve (Sep 04 2018 at 22:00):
I'm now completely confused as-to how I should construct this "create or update" transaction for multiple resources
I'm not sure about this. Is 'multiple resources' important somehow?
Sean McIlvenna (Sep 04 2018 at 23:24):
Yes... goes back to my attempts to load all us-core resources on FHIR servers.
Sean McIlvenna (Sep 04 2018 at 23:24):
https://gforge.hl7.org/gf/project/fhir/tracker/?action=TrackerItemEdit&tracker_item_id=17720
John Moehrke (Sep 05 2018 at 14:57):
Is there not a special case where the Resource you are POSTing has a business identifier ? Where in the case where the server has a Resource with that business identifier, it will do an UPDATE of that. But otherwise will do a CREATE? is the business identifier usable this way, or only the id?
Stefan Lang (Sep 05 2018 at 15:05):
@John Moehrke That's conditional update as defined in STU3.
You can use a business identifier or basically any search criteria that would lead to 0..1 matches and do a create or update accordingly.
Stefan Lang (Sep 05 2018 at 15:10):
I think the open question here is: does the definition in the current build still allow that? And if not, should that definition be changed to allow it again?
Patrick Werner (Sep 05 2018 at 15:16):
I think the only ambiguous part of the current spec is here:
http://build.fhir.org/http.html#cond-update
The resource MAY contain an id element, but does not need to (this is one of the few cases where a resource exists without an id element). If an id is provided, the server SHALL ignore it - see documentation for the update interaction.
This contradicts the "Update as Create": http://build.fhir.org/http.html#upsert
Patrick Werner (Sep 05 2018 at 15:17):
upsert is useful with traditional PUT or conditional Updates
Stefan Lang (Sep 05 2018 at 15:18):
True.
Plus: in STU3 "No match" meant: create. In current build, if the server does not support "Update as create", it must throw an error.
Basic UPSERT is gone.
Patrick Werner (Sep 05 2018 at 15:24):
Maybe we should distinguish between
- "NO MATCH - no ID provided" -> Create
- "NO MATCH - ID provided -> Update as Create (if the server supports it)
Stefan Lang (Sep 05 2018 at 15:26):
@Patrick Werner That's exactly what I think.
"Update or Create" (aka "Conditional Update" or "UPSERT") is not compatible with "Update as Create" otherwise
Eugene Lubarsky (Sep 11 2018 at 02:02):
It would be great to clarify this. The current wording has come from GF#16549 (https://github.com/HL7/fhir/commit/098f965b5694f683ba3d593564f698c031777ef2) which doesn't seem to intend to disallow upserts with server-assigned IDs (which would be an issue for me and I suspect many others). The current trunk text for conditional updates even says "The resource MAY contain an id...If an id is provided, the server SHALL ignore it" and there is no id in the URL.
Angus Millar (Sep 13 2018 at 09:01):
Interestingly I managed to implement the bundle transaction processing to behave as suggested here from reading the STU3 spec. At least I just tested and it seems to do as your require. Here is a simple Transaction Bundle example with a Patient and Observation resource where the Patient gets added with the supplied Resource ID as it is a PUT and the Observation is created with a server assigned id as it is a POST. If you POST the same transaction bundle again only the Observation is created and the patient will be updated. I think that is what you're looking for.
GET: https://stu3.test.pyrohealth.net/fhir/Bundle/transactionExampleUpdateOrCreate2
You can change the identifiers in that example and POST that transaction bundle to https://stu3.test.pyrohealth.net/fhir
to test again.
The server always treats any PUT as a conditional Create or Update as defined here in the spec: http://hl7.org/fhir/http.html#update
Or am I missing something?
Stefan Lang (Sep 13 2018 at 09:25):
@Angus Millar Right, that's the behavior when you know the id.
For what is described under "conditional update" (without id, but with search parameter(s)), I would hope for the same behavior. Which happens to be the case in STU3, but not in current build.
Current build refers to ids in that case (section "Update as create"), but usually, when you update by search, you don't have an id
Stefan Lang (Sep 13 2018 at 09:30):
I would like to open a tracker item on that, with the proposed solution of changing http://build.fhir.org/http.html#cond-update to contain the text @Patrick Werner wrote above:
"NO MATCH - no ID provided" -> Create "NO MATCH - ID provided -> Update as Create (if the server supports it)
Stefan Lang (Sep 13 2018 at 09:31):
Any objections (or affirmations) on that?
Angus Millar (Sep 13 2018 at 09:38):
So you mean like this one:
GET: https://stu3.test.pyrohealth.net/fhir/Bundle/transactionExampleUpdateOrCreate4
Now I am not assiging the Id for Patient the server is, but it first searches for the correct Patient resource based on a search parameter and business identifier?
Angus Millar (Sep 13 2018 at 09:39):
Are sorry so something changed between STU3 and R4. That will be what I'm not aware of.
Brian Reinhold (Sep 13 2018 at 09:40):
@Angus Millar Are you sure about the statement "The server always treats any PUT as a conditional Create or Update? A conditional Create uses a POST and is different from a Conditional Update. A Conditional create does not update if ONE resource is found that matches the criteria (it just returns doing nothing) and if none are found it does a create. That's my understanding.
Stefan Lang (Sep 13 2018 at 09:42):
@Angus Millar exactly.
And I assume(d) that "conditional Create or Update" was meant to mean "UPSERT"
Brian Reinhold (Sep 13 2018 at 09:44):
Any objections (or affirmations) on that?
@Stefan Lang I would say no to the second line. A conditional update is a PUT and that is where the uploader can specify the logical id. So if the resource is not found and a conditional update is done (with a logicial id) the resource is created using the logical id specified by the uploader. In a create you do not specify a logical id (unless a temporary id in a transaction bundle)
Stefan Lang (Sep 13 2018 at 09:48):
So that would basically mean returning to the way it is specified in STU3...
I think, the "Create as Update" was added for the reason to allow the client to specify the id in certain well defined use cases. And if that is allowed for the basic update, it should also be allowed for conditional update
Brian Reinhold (Sep 13 2018 at 09:49):
@Angus Millar exactly.
And I assume(d) that "conditional Create or Update" was meant to mean "UPSERT"
@Stefan Lang My understanding of a Conditional Create (which I use extensively in PHD uploads in transaction bundles) is that if one and only one resource is found matching your selection criteria, nothing happens. No change to the existing resource is made and the server responds with 200 OK for that resource. If NO resources are found a CREATE is done with the server specifying the logical iD (the uploader is not allowed to specify a logical id). If more than one resource is found matching your criteria a 4xx error is returned.
Angus Millar (Sep 13 2018 at 09:49):
@Angus Millar Are you sure about the statement "The server always treats any PUT as a conditional Create or Update? A conditional Create uses a POST and is different from a Conditional Update. A Conditional create does not update if ONE resource is found that matches the criteria (it just returns doing nothing) and if none are found it does a create. That's my understanding.
Sorry, I was misusing terminology, all I meant to say is that a PUT will update if it finds a resource with the given id or it will create the resource with the Id provided if not found. As per this sentence from the spec: "The update interaction creates a new current version for an existing resource or creates an initial version if no resource already exists for the given id." I should not have said 'Conditional Create' as that is somthing else as you point out.
Stefan Lang (Sep 13 2018 at 09:50):
@Brian Reinhold completely agreed. We are talking "conditional update" here, not "conditional create". As Angus just clarified
Brian Reinhold (Sep 13 2018 at 09:56):
So that would basically mean returning to the way it is specified in STU3...
I think, the "Create as Update" was added for the reason to allow the client to specify the id in certain well defined use cases. And if that is allowed for the basic update, it should also be allowed for conditional update
Isnt that what conditional update already does? When I did conditional updates, I specified the logical id (I assumed I had to but maybe that was a false assumption). In any case, I wanted to specify the logicial id because I needed that logical id in subsequent uploads in a streaming situation and I (1) did not want to wait for a server response to get it or (2) was queuing data for a third-party sender that knew nothing of FHIR.
The conditional update then created the resource with my logical id if the resource was not found. If it was found, the resource was updated. Does the 'create as update' apply to something other than the conditional update? To me it seems the conditional update DOES do a create as update...and always has (at least the last time I used it which was a long time ago!)
Angus Millar (Sep 13 2018 at 10:00):
I agree although I think you mean normal Update not Conditional Update, im reading R4 and like you I see no differance between these two statments :
Update: "The update interaction creates a new current version for an existing resource or creates an initial version if no resource already exists for the given id. "
AND
Update as Create: "Servers MAY choose to allow clients to PUT a resource to a location that does not yet exist on the server - effectively, allowing the client to define the id of the resource. "
Stefan Lang (Sep 13 2018 at 10:03):
I'm specifically talking about conditional update.
The spec there currently just says: "No matches: The server treats the interaction as an Update as Create interaction (or rejects it, if it does not support Update as Create)".
And "Update as Create" is an optional thing here and it's about Resource.id. Which leaves you with "reject the create, when you don't support "Update as Create". Meaning: update, if it exists, throw it away if not.
So this is just the keep the "old" behavior
Brian Reinhold (Sep 13 2018 at 10:04):
I agree although I think you mean normal Update not Conditional Update, im reading R4 and like you I see no differance between these two statments :
Update: "The update interaction creates a new current version for an existing resource or creates an initial version if no resource already exists for the given id. "
AND
Update as Create: "Servers MAY choose to allow clients to PUT a resource to a location that does not yet exist on the server - effectively, allowing the client to define the id of the resource. "
@Angus Millar Maybe the create as update means something I would REALLY like to have had: If the resource is found NO update is done. The resource is left alone! If the resource is not found, it is created with my logical id. THAT would have been a dream solution for me but in STU3 such an option does not exist. If that exists now, it will be a great addition because I could really use it!!!
Stefan Lang (Sep 13 2018 at 10:07):
@Brian Reinhold I agree with that. I just want to be able to also have the STU3 variant in the context of conditional update.
Angus Millar (Sep 13 2018 at 10:12):
Is that dream not 'if-none-exsists: _id =123' function on a create
Brian Reinhold (Sep 13 2018 at 10:15):
@Brian Reinhold I agree with that. I just want to be able to also have the STU3 variant in the context of conditional update.
@Stefan Lang Shake some of the cobwebs out of my mind; its been many years since I did the conditional update. But as I recall in the STU3/DSTU2 version the difference between a conditional update and update is that in the conditional case your match was based on something else other than the logical id.
Is that dream not 'if-none-exsists: _id =123' function on a create
YES!!!
Right now a conditional create does not allow the specification of a logical id when the resource is created. I want a situation where I can specify the logical id (because I need it in other resources and I don't want to wait or can't wait for a server to respond and give it to me) and have the server create the resource with that logical id if it does not exist BUT if it does exist LEAVE IT ALONE ... no update, not even of the internal metadata.
Angus Millar (Sep 13 2018 at 10:18):
Sounds like a 'if-none-exist: _id =123' yet on a PUT update rather than a POST create. So that is still a dream
Stefan Lang (Sep 13 2018 at 10:19):
@Brian Reinhold exactly. Which is why the current description of "Update as Create" (client defined id) is fine in the context of a basic Update (I have an id there), but not for Conditional Update (I explicitely have no id there)...
Stefan Lang (Sep 13 2018 at 10:21):
Anyway, a Conditional Update with "Update as Create" would still allow the client to define an id for a resouce that not yet exists.
But as described now, having no id will just lead to the resource being discarded instead. Which I consider bad.
Stefan Lang (Sep 13 2018 at 10:22):
... because not knowing the id is the whole reason for Conditional Update ...
Brian Reinhold (Sep 13 2018 at 10:24):
I agree although I think you mean normal Update not Conditional Update, im reading R4 and like you I see no differance between these two statments :
Update: "The update interaction creates a new current version for an existing resource or creates an initial version if no resource already exists for the given id. "
AND
Update as Create: "Servers MAY choose to allow clients to PUT a resource to a location that does not yet exist on the server - effectively, allowing the client to define the id of the resource. "
@Angus Millar Correct me if I am wrong (its been years) but the DSTU2/STU3 conditional update vs update was to allow the update to be done based upon something other than the logical id. You may not know the logical id and you want to make sure the resource has not already been created. If it hasn't been created, it gets created with the logical id you specify (didn't you HAVE to specify a logical id in an update?)
If it exists, the resource gets (unfortunately for me) updated. I do not know if the logical id you specified gets updated too but I doubt it. If multiple resources are found, error! Make better selection criteria.
A normal update is all based upon the logical id and it is found and updated or not found and created with you logical id
Brian Reinhold (Sep 13 2018 at 10:32):
Update as Create: "Servers MAY choose to allow clients to PUT a resource to a location that does not yet exist on the server - effectively, allowing the client to define the id of the resource. "
@Angus Millar Update as create difference I am assuming is that NO update gets done if the resource exists...at least I hope so. That is an option that does not currently exist. Maybe a better wording is Create as Update (I specify the logical id). If the resource does not exist, create with my logical id and do nothing if the resource exists.
Stefan Lang (Sep 13 2018 at 10:34):
@Brian Reinhold that#s about the "One Match" part then. For Conditional Update:
"One Match: The server performs the update against the matching resource"
Angus Millar (Sep 13 2018 at 10:35):
I think it was not ever made clear, if you do a Conditional Update where you provide a search parameter and that search parameter returns one resource, then an update is done on it. Yet if it returned no resource a create is done, yet it never talked about whether that resource MUST have a resource Id in it or not. I know my server, if you do give a resource id, in the resource on a conditional update, I check it matches the found resource id from the search and fail the update if it does not match . Yet if you provide no resource id in the resource then I just perform the update on the found resource. And furthermore, if not resource is found I do the create with your Resource id in the resource or if none I assign a server resource id and create.
Stefan Lang (Sep 13 2018 at 10:36):
But that would be a Conditional Create as stated above?
Stefan Lang (Sep 13 2018 at 10:39):
Before completely moving away from the original issue, I just created a tracker on that: GF#17906
Angus Millar (Sep 13 2018 at 10:39):
Well, Conditional Create and Conditional Update are similar but they have differences.
CReate: One Match: The server ignores the post and returns 200 OK
Update : One Match: The server performs the update against the matching resource
Angus Millar (Sep 13 2018 at 10:40):
And Create never lets the user define the resource id
Stefan Lang (Sep 13 2018 at 10:43):
If defining the id is considered necessary on the "Create but not Update" case, this may indeed be another issue
Brian Reinhold (Sep 13 2018 at 10:43):
I think it was not ever made clear, if you do a Conditional Update where you provide a search parameter and that search parameter returns one resource, then an update is done on it. Yet if it returned no resource a create is done, yet it never talked about whether that resource MUST have a resource Id in it or not. I know my server, if you do give a resource id, in the resource on a conditional update, I check it matches the found resource id from the search and fail the update if it does not match . Yet if you provide no resource id in the resource then I just perform the update on the found resource. And furthermore, if not resource is found I do the create with your Resource id in the resource or if none I assign a server resource id and create.
@Angus Millar Are you implementing a server? I am impressed! All power to you!
Here are my understandings of the creates, updates, and conditional variants (versions 2 and 3, I have not looked at 4)
create: cant specify a logical id. The resource is always created and the server gives it the logical id
conditional create: can't specify a logical id. Resource is created if no resource is found matching criteria
ONE Match: server returns doing nothing. Resource is left alone and remains as is.
Multiple matches: Error. Your selection criteria stink
update: client specifies the logical id. Server creates resource with logical id if not found. Updates resource if found
conditional update: client specifies logical id but resource is searched for based on other criteria. No match, create with specified logical id
ONE match: update the resource (if the logical ids are different, I am assuming the new one is ignored)
Multiple matches: your criteria stink. Error
Digging into the dust of 3.0.1 here is where an update is required to have a client specified logical id:
The request body SHALL be a Resource with an id element that has an identical value to the [id] in the URL. If no id element is provided, or the value is wrong, the server SHALL respond with an HTTP 400 error code, and SHOULD provide an OperationOutcome identifying the issue.
Stefan Lang (Sep 13 2018 at 10:48):
Conditional Update is to my understanding not about the client specifying a logical id in STU3. The "client specifies id" is "Update as Create" as explicitely referred to in R4. And it is an optional functionality on the server. Plus: if the server does not support that functionality, the resource will be rejected in the "No matches" case. Which I still consider bad ;-)
Angus Millar (Sep 13 2018 at 10:51):
If it is optional then why does the normal update say "he update interaction creates a new current version for an existing resource or creates an initial version if no resource already exists for the given id", I still see no differance between normal update and this new ' Update as Create'
Stefan Lang (Sep 13 2018 at 10:51):
The request body SHALL be a Resource with an id element that has an identical value to the [id] in the URL. If no id element is provided, or the value is wrong, the server SHALL respond with an HTTP 400 error code, and SHOULD provide an OperationOutcome identifying the issue.
Yes. But that's for update, not for conditional update:
STU3: "When the server processes this update, it performs a search using its standard search facilities for the resource type, with the goal of resolving a single logical id for this request" - so the server finds the id, the client doesn't provide it
Stefan Lang (Sep 13 2018 at 10:53):
"Update as Create" simply clarifies what has to happen in the "No matches" case when a client provides an id
Angus Millar (Sep 13 2018 at 10:53):
Agree, so are we saying that if they do provide the id in the resource on a conditonal Update then that is an error?
Stefan Lang (Sep 13 2018 at 10:55):
That would disallow a client to specify the id on Conditional Update.
So my proposal for Conditional Update is:
- No matches, no id provided: The server creates the resource.
- No matches, id provided: The server treats the interaction as an Update as Create interaction (or rejects it, if it does not support Update as Create)"
Angus Millar (Sep 13 2018 at 10:55):
"Update as Create" simply clarifies what has to happen in the "No matches" case when a client provides an id
OK I can accept that, good point
Angus Millar (Sep 13 2018 at 10:58):
That would disallow a client to specify the id on Conditional Update.
So my proposal for Conditional Update is:
- No matches, no id provided: The server creates the resource.
- No matches, id provided: The server treats the interaction as an Update as Create interaction (or rejects it, if it does not support Update as Create)"
I'm on board with all this wiht an extra that I do:
One Match and match resource id not equal to provided resource id, reject
Stefan Lang (Sep 13 2018 at 11:00):
Good point. Maybe add a comment to the tracker? GF#17906
Brian Reinhold (Sep 13 2018 at 11:00):
"Update as Create" simply clarifies what has to happen in the "No matches" case when a client provides an id
OK I can accept that, good point
@Stefan Lang agreed. The conditional update was a little vague about the creation. The HAPI FHIR server happened to take my logical id when it created the resource. So its conditional update was like the update except it did a search for the resource based upon selection criteria. Since the way id did it (the logical id was actually created from the selection criteria) there would never be a conflict. In other words, if I had already created the resource it would have the same logical id I would have in my conditional update attempt. Would have been interesting to see what would have happened if I put in a logical id that was different.
Angus Millar (Sep 13 2018 at 11:01):
So that is :
One Match: no resource id provided, create ands assign new id
One Match resource id provided and it matches the found resource ,update that resourece
One Match resource id provided does not match resource found , reject update
And, everthing you wrote.
Brian Reinhold (Sep 13 2018 at 11:03):
Good point. Maybe add a comment to the tracker? GF#17906
Is there a situation in R4 (I have not checked) where one can have the resource created if it does NOT match the selection criteria with the specified logical id AND if one match is found THE RESOURCE IS LEFT ALONE??? NO update!!!
Angus Millar (Sep 13 2018 at 11:04):
Got run, feel free to play around with this on my server here, woudl love the testing :
https://pyrohealth.net/
FHIR Endpoint: https://stu3.test.pyrohealth.net/fhir
Brian Reinhold (Sep 13 2018 at 11:08):
Got run, feel free to play around with this on my server here, woudl love the testing :
https://pyrohealth.net/
FHIR Endpoint: https://stu3.test.pyrohealth.net/fhir
@Angus Millar Do you have a server supporting R4 3.6.0? Does it support the new Device resource and transaction bundle?
Angus Millar (Sep 13 2018 at 11:08):
Working on R4 now. So no not yet.
Brian Reinhold (Sep 13 2018 at 11:09):
Working on R4 now. So no not yet.
So what version is it? 3.1.0, 3.20?
Angus Millar (Sep 13 2018 at 11:10):
STU V3.0.1
Stefan Lang (Sep 13 2018 at 11:14):
@Brian Reinhold
I'm not aware of such a situation being allowed. Might require another header param for Conditional Create?
Brian Reinhold (Sep 13 2018 at 11:23):
@Brian Reinhold
I'm not aware of such a situation being allowed. Might require another header param for Conditional Create?
It might be easier just to make the decision upon whether the logical id is present. If the resource is not found with the given selection criteria, the resource is created. If the logical id is specified, that logical id is used (if the server already uses that logical id an error is returned. The client needs to be smarter about specifying the logical id). If not, the server creates it. The important thing is if the resource is found, do nothing!
Many clients are in a situation where they cannot wait for a server response to get a logical id but need that logical id for upcoming resources. For example, handling streaming data from an ECG. Each Observation references the patient and device via logical id. In some cases Observation A is referenced by Observation B sent at a later time.
Stefan Lang (Sep 13 2018 at 11:27):
That's probably the original intention of "Update as Create" - except that you don't want to update
Brian Reinhold (Sep 13 2018 at 11:27):
That's probably the original intention of "Update as Create" - except that you don't want to update
Right!
Stefan Lang (Sep 13 2018 at 11:31):
But basically ... if you ensure that the client created id doesn't already exist on the server, you get what you want.
As stated in http://build.fhir.org/http.html#upsert :
"Alternatively, clients may be sharing an agreed identification model (e.g. key server, scoped identifiers, or UUIDs) where clashes do not arise. Note that this use of update has security implications. "
Stefan Lang (Sep 13 2018 at 11:32):
In this case, Conditional update WITH Update as Create would do what you want
Stefan Lang (Sep 13 2018 at 11:34):
Somebody should draw a diagram on that whole thing ...
Patrick Werner (Sep 14 2018 at 08:33):
something like this?: conditional_update.png
(fixed version)
Brian Reinhold (Sep 14 2018 at 08:42):
something like this?: conditional_update.png
@Patrick Werner if the condition matches only once on a conditional create you do nothing. That's the point. Why are you creating a resource when the condition matches?
I would like a situation where if the condition matches one does nothing BUT if the resource is not found it is created with my provided id. As far as I know that option does not exist. For many clients, especially on small resource-limited platforms, handling a server response to get ids that are needed in resources being concurrently generated is complicated, one needs queuing and thus memory resources. An example of such a situation is sending streaming pulse oximeter data from a home environment.
Patrick Werner (Sep 14 2018 at 08:46):
You are talking about Conditional Creates, this is about Conditional Updates
Patrick Werner (Sep 14 2018 at 08:47):
What you are searching already exists: https://www.hl7.org/fhir/http.html#ccreate
Patrick Werner (Sep 14 2018 at 08:48):
@Stefan Lang or take this one if you prefer DMN over BPMN conditional_update_DMN.png
Brian Reinhold (Sep 14 2018 at 08:49):
What you are searching already exists: https://www.hl7.org/fhir/http.html#ccreate
@Patrick Werner I see. You have 'conditional POST'. If you are talking about conditional updates use 'conditional PUT'. The POST makes it a conditional create.
Patrick Werner (Sep 14 2018 at 08:49):
omg, thx :-) fixed it above
Brian Reinhold (Sep 14 2018 at 08:54):
omg, thx :-)
Given that, I am still a little confused about the what you do when a single match is found and a logical id provided. In that case you create a new resource in spite of the fact a resource already exists with the condition specified. Why does this happen and not just an update? I would expect the logical id is provided for the case where a resource is not found and one is made using that logical id.
Patrick Werner (Sep 14 2018 at 08:57):
you are right, i did my diagram based on the GF Tracker item, which includes these from you:
Copy & paste additional proposal by Angus Millar:
One Match: no resource id provided, create ands assign new id
One Match resource id provided and it matches the found resource ,update that resourece
One Match resource id provided does not match resource found , reject update
Patrick Werner (Sep 14 2018 at 08:58):
but you are right
Patrick Werner (Sep 14 2018 at 08:58):
One Match should only have two results:
- Update
- REJECT
Brian Reinhold (Sep 14 2018 at 09:01):
you are right, i did my diagram based on the GF Tracker item, which includes these from you:
Copy & paste additional proposal by Angus Millar:One Match: no resource id provided, create ands assign new id
One Match resource id provided and it matches the found resource ,update that resourece
One Match resource id provided does not match resource found , reject update
The 'One Match: no resource id provided, create ands assign new id' makes no sense to me. The idea that you found a match indicates that the resource you are looking for exists and is the only one that exists with your criteria. If you want to make a new resource, just do it why go through all the matching logic? With that statement the result is the same whether there is a match or not. Well, if there are multiple matches then there is a reject.
Stefan Lang (Sep 14 2018 at 09:02):
Right, no create should happen when one match is found
Patrick Werner (Sep 14 2018 at 09:02):
Yes
Patrick Werner (Sep 14 2018 at 09:03):
alright here you go (again) conditional_update.png
Patrick Werner (Sep 14 2018 at 09:05):
Stefan Lang (Sep 14 2018 at 09:07):
I think in the diagram this should be "No resource id provided or resource id and found-resource-ID are matching"
Stefan Lang (Sep 14 2018 at 09:10):
DMN:
rows 2 and 3 need "false" in the "multiple matches" column
and a row "3a" is needed: true/false/false/-/UPDATE
Brian Reinhold (Sep 14 2018 at 09:17):
On a conditional update my understanding is this
1. A condition is specified
2. IF one and only one resource is found, it is updated (otherwise error). Any provided logical id by the client is ignored. - 'the conditional part of the update'
3. If no matches are found, the resource is created with the logical id provided by the client - classic update transaction
4. The new thing is (as I understand it) if the logical id is not provided, the resource is created where the server generates the logical id.
Step 4 was added as a clarification because in the classic update, it is clear that one had to specify a logical id. In the conditional update, that statement was not explicitly made. So now we have the option to specify or not specify a logical id. It also satisfies a different use case; one where the client does not know the logical id. I had a use case where I knew what the logical would be if the resource had been created but what I didn't know was if it was already created. So I wanted to check for existence first (without doing a GET). If it didnt exist I wanted to create it with my id. But if it did exist, I wanted to do nothing but using the conditional update would cause the existing resource to be updated (even though the content of the resource was identical).
Stefan Lang (Sep 14 2018 at 09:19):
Step 3 actually is "Update as Create".
Step 4 is the STU3 behavior for conditional update with no matches
Brian Reinhold (Sep 14 2018 at 09:24):
Step 3 actually is "Update as Create".
Step 4 is the STU3 behavior for conditional update with no matches
@Stefan Lang I think you have it backwards. In a create transaction you are not allowed to specify a logical id. In an update transaction, you are required to specify a logical id. When I did a conditional update on a HAPI FHIR server, I always specified the logical id and it would generate the resource if it did not exist with my logical id. I never tried doing a conditional update without specifying a logical id.
In a conditional create I am not allowed to specify a logical id (unless it is a temporary id in a bundle but that's a different story).
Stefan Lang (Sep 14 2018 at 09:26):
AFAIK the whole use of conditional update is not knowing the id
Patrick Werner (Sep 14 2018 at 09:28):
Step 3 actually is "Update as Create".
Step 4 is the STU3 behavior for conditional update with no matches
Rule 3 is Update: i have a matching Condition, and a matching provided ID -> UPDATE
Patrick Werner (Sep 14 2018 at 09:29):
and RULE4 is the same as in STU3
Stefan Lang (Sep 14 2018 at 09:30):
Brian's Step 3 says "If no matches are found" => create ;-)
Patrick Werner (Sep 14 2018 at 09:31):
i agree, but you could do a condUpdate with a search criteria despite the fact that you know the ID. (Maybe making shure this resource only exists once on the server)
Brian Reinhold (Sep 14 2018 at 09:31):
AFAIK the whole use of conditional update is not knowing the id
I had a slightly different use case; I knew what the logical id would be (it was specified by a standard). What I didn't know was if the resource had already been created.
But not knowing the logical id is fine, too. Thus you provide the condition. This does not prevent you from specifying the logical id in case the resource needs to be generated. What was not clear in STU3 version was if you are doing a conditional update, do you still have to specify a logical id for the case where the resource is not found. In a classic update, the spec says you have to provide a logical ID. What R4 is doing is saying in a conditional update, you can either specify the logical id or not. If you don't, a no-match case is handled like a create and not an update.
Patrick Werner (Sep 14 2018 at 09:34):
DMN:
rows 2 and 3 need "false" in the "multiple matches" column
actually it doesn't (Rule1 already handles all multiple matches) but i added it for clarification. conditional_update_DMN.png conditional_update.png
Stefan Lang (Sep 14 2018 at 09:35):
rows 2 and 3 need "false" in the "multiple matches" column
actually it doesn't (Rule1 already handles all multiple matches) but i added it for clarification.
Right, but thanks anyway ;-)
Stefan Lang (Sep 14 2018 at 09:37):
I agree on both table and diagram
Brian Reinhold (Sep 14 2018 at 09:42):
and RULE4 is the same as in STU3
Not quite. This is where STU3 was vague. It wasn't clear what would happen if the resource was found and no logical id was provided. Given that the classic update required it, does this mean an error? I think R4 is trying to clarify this situation by saying ok, we allow both. Existing id will do an update and no id will do a create.
What probably happened was some servers, after finding no match, handed the transaction to its 'update' method. That would cause an error if no id were provided. Now it needs to check for an id. If found, use the update method. If not, use the create method. Probably not too much extra work.
Brian Reinhold (Sep 14 2018 at 09:50):
DMN:
rows 2 and 3 need "false" in the "multiple matches" columnactually it doesn't (Rule1 already handles all multiple matches) but i added it for clarification. conditional_update_DMN.png conditional_update.png
@Patrick Werner I don't know what should happen if the resource is found and the logical id is specified but does not match the logical id of the found resource. Should that be an error? Say I don't know the logical id but want to generate (I use generate instead of create to avoid confusion) the resource if it is not found WITH this logical id. If the resource is found with my conditions but it does not have my specified logical id, is that an error? I don't know. I would (personally) prefer that the specified logical id be looked at only if a resource is being generated. If it already exists, ignore it.
Patrick Werner (Sep 14 2018 at 10:00):
i disagree, if i provide an id in a conditional update (which is already an edge case) it should behave similar to a regular update.
UPDATE:
The request body SHALL be a Resource with an id element that has an identical value to the [id] in the URL. If no id element is provided, or the id disagrees with the id in the URL, the server SHALL respond with an HTTP 400 error code, and SHOULD provide an OperationOutcome identifying the issue.
Brian Reinhold (Sep 14 2018 at 10:35):
i disagree, if i provide an id in a conditional update (which is already an edge case) it should behave similar to a regular update.
UPDATE:
The request body SHALL be a Resource with an id element that has an identical value to the [id] in the URL. If no id element is provided, or the id disagrees with the id in the URL, the server SHALL respond with an HTTP 400 error code, and SHOULD provide an OperationOutcome identifying the issue.
But as Stefan says, isn't the conditional update for when you don't know the logical id? The conditional is a different use case. A classic update is designed to update a resource that you know exists and know its id and if it doesnt exist you want to generate it with a specific id.
Conditional is different. You could do a GET based upon your search conditions (if you dont know the id) to see if the resource exists and then update it if it doesnt (specifying the id). But that involves two transactions and permission to obtain PHI from the server. The conditional is attempting to allow you to accomplish all that in one transaction without the need for permissions to extract data from the server.
Ewout Kramer (Mar 25 2019 at 21:07):
The proposed resolution pointed to in this discussion was adopted in R4, but recently, @Josh Mandel raised a valid question on GF#20390. The discussion above (which is now part of the R4 spec) uses the phrase "id provided" and "the logical id" pretty informally. In the case of a conditional PUT, the FHIR REST URL does not have an id (as it would for a normal PUT), so where exactly does this "provided id" live? In Resource.id? Or in the _id search parameter?
It's conceivable that you'd have search criteria without an _id, but want to conditionally create a resource with a given Resource.id. Yet the last sentence in the text on conditional updates says: "If an id is provided, the server SHALL ignore it" - so this suggests we cannot use Resource.id
Anyway, I suspect this refers to Resource.id, and we should remove the last sentence of that paragraph, but in a FHIR-I discussion with some implementers on the call, we could not reach a final conclusion, and we all had our own differing interpretation of the current R4 text.
What to do about it?
Kenneth Myhra (Mar 26 2019 at 11:45):
The introduction of id provided introduces IMO a subtle second criteria (Resource.id).
If you have a Resource.id and your intention is to update an existing or create a new resource by id provided, shouldn't you then just use Update as create?
While if I want to do a Conditional update I explicitly define my search parameters on the query string and if I accidentally forget to remove Resource.id the server disregards the id and creates a new resource if no matches.
Kenneth Myhra (Mar 26 2019 at 19:17):
Disregard my comment above, I think I can see the use-case for this and therefore agree with Ewout's conclusion to remove the paragraph stating: "If an id is provided, the server SHALL ignore it". Also misinterpreted the "Update as create" thinking it meant it would update that resource if it is was found, rather it is a Create operation and will only create the resource using the provided id if not found.
Last updated: Apr 12 2022 at 19:14 UTC