Linkage between FHIR resources - hl7

For Lab Reports, in FHIR (http://hl7.org/implement/standards/fhir/) if you consider the "DiagnosticReport" resource you can see that it can contain multiple "Observation" resources.
When querying a FHIR based server it would then be possible to query the "DiagnosticReport" resource for a complete Lab Report, or if required an individual "Observation" resource.
The linkage from "DiagnosticReport" to "Observation" resource is clear.
Is there a way to work the links in reverse?
i.e. can you query to see which (if any) "DiagnosticReport" that a particular "Observation" was part of?

Links are navigated in reverse by some kind of indexing system. In the RESTful context, that equates to a search parameter. So if you have an observation 12-34-56, then you can find all the diagnostic reports that include it:
[base]/diagnosticreport/?result=12-34-56
I think the definition of the search parameter "result" could be clearer. I'll make it so.

Related

OneM2M, IOTKETI Mobius RETRIEVE Group Member ContentInstances

In my example architecture; I have an IN-Mobius and a ADN-AE-Thyme (nCube Thyme).
First of all; i created a AE which is called "ae_test_02", i can GET this resource via Postman.
After this step; i run ADN-AE-Thyme, thyme.js, and it created a container which is called "thyme_01", and also i can GET this resource via Postman.
Also in that step, thyme.js add containerInstances into the "thyme_01" container. Then, i can get that latest containerInstance with "/la" parameter via Postman
In this point, the problem has began. I create a group resource, while creating i tried couple solutions, always fail. I tried in "mid" attribute;
{ "m2m:grp": {
"rn": "grp_test_100520_08",
"mt": 3,
"mid": ["3-20200505012920476/la",
"Mobius/3-20200505012920476/la",
"Mobius/thyme_01/la",
"Mobius/ae_test_02/3-20200505012920476/la",
"Mobius/ae_test_02/thyme_01/la",
"ae_test_02/thyme_01/la",
"ae_test_02/3-20200505012920476/la"],
"mnm": 10
}
The problem is that, i tried these mid paths one by one, but never works. When i try to get latest containerInstances via Postman, i use this URL and the results is "resource does not exist (get_target_url)"
The containers and contentInstances in the IN-Mobius, and i requested to the IN-Mobius. By using these informations how should i implement group "mid" attribute; for the get containerInstances via group resources ?
First Edit.
Hi Andreas.
For the first issue, i can get resource correctly. In this point my aim is GET containerInstance in the container, which is a member (mid) in that .
Second; now I understand, there is not existing resource in resource, okay. As you mentined, i want to pass a request to all member (containers) of a resource. For this purpose, i will use https://localhost:7579/Mobius/grp_test_100520_08/fopt, but it gives an error "ERR_INVALID_ARG_TYPE". I know that, at least one mid structure is correct, but which one is the correct ?
For the smaller issue, i already know that resouce multiple times in the mid attribute, because i did not know which one is the correct adressing scheme ?
Also, while creating a resource, the resource should be in the ae resource (/Mobius/ae_test_02/grp_name) or in the Mobius (/Mobius/grp_name)
resources can be in directly in IN-Mobius or should in MN-Rosemary? Is fanOutPoint only using by external resource like MN or even IN, fopt using ?
Second Edit.
The "thyme" comes from nCube Thyme (https://github.com/IoTKETI/nCube-Thyme-Nodejs), it creates a container and then randomly create ContainerInstances.
The resource tree looks like;
Mobius >> ae_test_02 (AE resource) >> thyme_01 (Container It created from nCube Thyme https://github.com/IoTKETI/nCube-Thyme-Nodejs) >> ContainerInstances
I have also a resource in >> Mobius >> grp_test_100520_08 (GROUP resource which is uses)
I tried;
{ "m2m:grp": {
"mid": ["Mobius/ae_test_02/thyme_01"],
"mnm": 5
}
}
In this request, fopt.js gives an error "callback is not a function".
{ "m2m:grp": {
"mid": ["ae_test_02/thyme_01"],
"mnm": 5
}
}
In this request, fopt.js gives same "callback is not a function", but in different line.
I guess my fopt.js file is old, then i checked mobius github page and get that file, however it not solve this.
Also my resource look like this;
Also my fopt.js file is same as this;
https://github.com/IoTKETI/Mobius/blob/master/mobius/fopt.js
UPDATE 3.
The "cnm" attribute problem is this; while creating a resouce, CSE will automaticly assign "cnm" attribute according to member size. However, CSE will not this process in UPDATE (PUT) request. From this point, i will create resources, not UPDATE them.
As you mentioned, i send requests to the group's resource, but it gives the "callback is not a function" error. To solve this problem, i downloaded and installed the whole distribution. (https://github.com/IoTKETI/Mobius) After that, i will do same processes again for understand the fopt.js file behaviour. The result wasn't changed, it gives the same error.
I planning to explain whole situation and create an issue, in Mobius github page. I hope they will response soon.
I think there are two issues with your example.
The first issue is with the request to the <Group>. You need to distinguish between requests to the <Group> resource itself and requests to the members of the <Grou>.
There is no child resource <la> of the <Group> resource itself. This is why you receive an error message. If you want to pass a request to all members of a <Group> resource then you need to target the virtual child resource <fopt>. In your case the request should target URI https://localhost:7579/Mobius/grp_text_100520/fopt. Since you already have the <la> resources as members you won't need to add the /la part to the request. However, I would recommend to only add the <Container> resources to the group and use the target URI https://localhost:7579/Mobius/grp_text_100520/fopt/la to retrieve the latest <ContentInstances> of each container.
The second (smaller) issue is that from what I can get from your example code that you add the same resource multiple times to the group, but only with different addressing schemes. Please be aware that the CSE must removes duplicate resources when creating or updating the mid attribute.
Edit after question update
It is not very clear what your resource tree looks like. So, perhaps you should start with only one resource references and continue from there. Valid ID's in the mid attribute are either structured (basically the path of the rn attributes) or unstructured ID's (the ri's). The CSE should filter the incorrect ID, so you should get the correct set of ID's in the result body of the CREATE request.
btw, where does "thyme" come from? This is only in a label, which does not form an ID.
Regarding the <fanOutPoint> resource: Normally all request would be targeted to the <Group> resource, but requests to the virtual <fanOuPoint> resource are forwarded to al the members of the group. If a resource referenced in mid is accessible then the request is forwarded and the result is collected and is part of the result body of the original request.
You also need to be careful and regard the resource types: only send valid requests to the group's members.
Update 2
From the IDs in the mid attribute of the <Group> resource it looks like that the CSE validated the targets (though the cnm (current number of members) is obviously wrong, which seems to be an error of the CSE).
So, you should be able to send requests to the group's <fopt> resource as discussed above.
For the CSE runtime error you should perhaps contact the Mobius developers. But my guess is that you perhaps should download and install the whole distribution, not only a single file.
for anyone in the future; who is dealing with this problem.
The problem is simply is that; in the app.js there is 4 function call (fopt.check). While calling the function in the app.js file, there are 5 parameter exists, on the other hand, while getting these arguments in the function it takes only 4 arguments. For this reason, body_obj always becomes "undefined" then it will never reach the "Container" or "ContainerInstance" source. Lately, KETI was sent a new commit to the Mobius Github page (https://github.com/IoTKETI/Mobius/commit/950182b725d5ffc0552119c5c705062958db285f) to solve this problem. It solves this problem unless you are using use_secure == 'disable'. If you try to use use_secure == 'enable' you should add an if statement to check use_secure and add import HTTPS module.
Also, while creating resource, defining the "mid" attribute is not very clear. Just for now, if you want to reach (latest) source; you should add "/la" for all members of the group. This is recommended by KETI on Github page issue 5.
(https://github.com/IoTKETI/Mobius/issues/5#issuecomment-625076540)
And lastly, thank you Andreas Kraft; your help was very useful.

How to get proper results for these queries?

Need to execute and return 1st order detail alone for each order. Below doesn't work
https://services.odata.org/Experimental/Northwind/Northwind.svc/Customers?$expand=Orders($expand=Order_Details;$top=1)
Need to filter records based on order id. Below doesn't work and throws "Term 'Orders($expand=Order_Details)$filter=OrderID eq '10643'' is not valid in a $select or $expand expression"
https://services.odata.org/Experimental/Northwind/Northwind.svc/Customers?$expand=Orders($expand=Order_Details)$filter=OrderID eq '10643'
Invalid but returned results
https://services.odata.org/Experimental/Northwind/Northwind.svc/Regions?expand=Order_Details
https://services.odata.org/Experimental/Northwind/Northwind.svc/Regions?expand=Territories
Not Returning Childrens
https://services.odata.org/Experimental/Northwind/Northwind.svc/Products?&expand=Suppliers
https://services.odata.org/Experimental/Northwind/Northwind.svc/Regions?&expand=Territories
https://services.odata.org/Experimental/Northwind is no longer 'Best Practise'
It's a bold statement, but this question proves that many advanced query features have not been fully or properly implemented in the published service.
While many developers may use it to practise OData query concepts, given that the OData implementation is largely up to the developers and the version of the packages they use, it is probably a of more commercial value if you query against a live or a dev implementation of the actual service that you want to query.
The following is an analysis of OPs queries and how to achieve the desired response according the the OData-V4 specification and verified against a deployed API that utilises the following NuGet packages:
Microsoft.AspNet.OData v7.3.0
Microsoft.OData.Core v7.6.2
The actual API that I used for testing is proprietary and cannot be published here.
According to the spec, you have to move the $top specifier to the Order_Details expansion.
https://services.odata.org/Experimental/Northwind/Northwind.svc/Customers?
$expand=Orders($expand=Order_Details($top=1))
However:
https://services.odata.org/Experimental/Northwind does not correctly implement $top query option within expansion as defined in 5.1.3 System Query Option $expand
Query options can be applied to an expanded navigation property by appending a semicolon-separated list of query options, enclosed in parentheses, to the navigation property name. Allowed system query options are $filter, $select, $orderby, $skip, $top, $count, $search, and $expand.
$top is however supported in the ODataLib v7+ (.Net) implementation of OData v4. So the syntax is correct, but you should check with your API developers for their opinion if your queries with this syntax do not work.
NOTE: When using $top you should also use $orderbyto ensure that the query results are reliable and reproducable:
https://services.odata.org/Experimental/Northwind/Northwind.svc/Customers?
$expand=Orders($expand=Order_Details($orderby=ProductID;$top=1))
To apply multiple query options within an expansion, you must separate then with a semi-colon: ;. However that alone will not prevent other customer records from being returned, so you must also add a root level filter as well, which is complicated by the fact that Orders is a collection. We can use the any function to only return customers that have an order with the specified Id:
Also note that OrderID is numeric, so do not wrap comparison values in quotes
https://services.odata.org/Experimental/Northwind/Northwind.svc/Customers?
$expand=Orders($expand=Order_Details;$filter=OrderID eq 10643)
&$filter=Orders/any(o:o/OrderID eq 10643)
this can be further simplified using parameter alias:
https://services.odata.org/Experimental/Northwind/Northwind.svc/Customers?
$expand=Orders($expand=Order_Details;$filter=OrderID eq #orderId)
&$filter=Orders/any(o:o/OrderID eq #orderId)
&#orderId='10643'
However:
https://services.odata.org/Experimental/Northwind does not correctly implement parameter aliases so you cannot verify the alias syntax against this service.
Also note
that experimental service is not correctly applying the filter to either the root elements or the navigation collection, the syntax shown here does however work against the .Net ODataLib implementations of OData v4.
The reason that your $expand is not working is that you have left off the $ from the parameter name. The OData query interpreter only identifies query options are parameters that start with $.
Eitherway, according to the https://services.odata.org/Experimental/Northwind/Northwind.svc/$metadata#Regions, there is no Order_Details navigation property to $expand on:
<EntitySet Name="Regions" EntityType="NorthwindModel.Region">
<NavigationPropertyBinding Path="Territories" Target="Territories" />
</EntitySet>
So when you try again with the correct syntax:
https://services.odata.org/Experimental/Northwind/Northwind.svc/Regions?$expand=Order_Details
you get the expected message:
Could not find a property named 'OrderID' on type 'NorthwindModel.Region'
The second attempt will work if you put the correct $ in there for the $expand query option:
https://services.odata.org/Experimental/Northwind/Northwind.svc/Regions?$expand=Territories
The OData query parser only looks for the expected query options with the $ prefix, this allows your API logic to still process other non-OData parameters as you see fit to do so. The other parameters therefor are still HTTP Url compliant parameters, the implementation at odata.org doesn't know what to do with them and they are simply ignored.
This is just another variation on the same issue with 3, the $ is missing. (I suspect that this URL was meant to be in 3: https://services.odata.org/Experimental/Northwind/Northwind.svc/Products?$expand=Suppliers)
So while https://services.odata.org/Experimental/Northwind is not 100% reliable, neither are the .Net ODataLib, SAP or MS Dynamics implementations. The spec is evolving and there are many query techniques that are not fully implemented in probably any providers at this stage.
Simply be mindful of this fact and when you run into issues using an API, the first point of contact should be the developers or the community that are supporting that particular API, it will be up to the developers what techniques and packages they use and at the end of the day to what extent they support the protocol as it is specified.

Nested Jira Search on two independent projects

I need to get a nested Jira search. I am okay with JQL query but I have a usecase that I don't know how to solve
Company uses project=XTBOW for reporting purpose for executives (Epic)
The company also uses project=XTA for underling development work (Task)
The XTA task are linked to the XTBOW Epic for a subset of task, but not all. (There is a large body of XTA task that are not linked to XTBOW)
I need to get a filter going for all XTA projects that are linked to XTBOW Epics only. I would like to use a filter like this:
project = XTA and "Epic Link" in (<project = XTBOW.key>)
I can manually prove this filter works. But need a way to automate this filter, because the number of tickets being created/tracked in growing exponentially, and if someone deletes a key for XTBOW that is in the "Epic Link" field, the JQL search throws and error because the "Key" is missing.
Example - FYI cf[10231] is the "Epic Link" field:
project in (XTA,XTWOF) and cf[10231] in (XTBOW-42,XTBOW-59)
The overall objective is to download the data to a dataframe. So if there is a better suggestion to even avoid JQL and do it through python. I am all ears. Just need so pointers to start. I am just going this route because I have already built a JIRA-Downloader/Parser using Python.
The easiest way to get subsets of issues is with:
search_issues(jql_str, startAt=0, maxResults=50, validate_query=True, fields=None, expand=None, json_result=None)
You should be able to just pull the issue sets using the queries you already created, just make them into strings.
DOC

Meteor publish-with-relations VS collection-helpers for joins?

What's the best way to do joins in Meteor/mongo? Use one of these packages, or something else:
publish-with-relations
https://github.com/erundook/meteor-publish-with-relations/blob/master/publish_with_relations.coffee
collection-helpers
https://github.com/dburles/meteor-collection-helpers
I'm very familiar with PWR, but collection-helpers is new to me. It looks like the two are complimentary.
PWR solves the somewhat complex problem of publishing documents to the client via a reactive join based on arbitrarily complex relationships. See this question for more details.
collection-helpers appears to be a set of convenience functions added to the client to be used when traversing collection relationships inside of a template (given that the required documents have already been published). For example, if you have books and authors in separate (but related) collections, you can immediately get myBook.author.fullName inside of a template without having to type out the extra find for the author.
currently the top popular solution in atmosphere seems to be publish-composite https://atmospherejs.com/reywood/publish-composite

How to GET a read-only vs editable resource in REST style?

I'm fairly familiar with REST principles, and have read the relevant dissertation, Wikipedia entry, a bunch of blog posts and StackOverflow questions on the subject, but still haven't found a straightforward answer to a common case:
I need to request a resource to display. Depending on the resource's state, I need to render either a read-only or an editable representation. In both cases, I need to GET the resource. How do I construct a URL to get the read-only or editable version?
If my user follows a link to GET /resource/<id>, that should suffice to indicate to me that s/he needs the read-only representation. But if I need to server up an editable form, what does that URL look like? GET /resource/<id>/edit is obvious, but it contains a verb in the URL. Changing that to GET /resource/<id>/editable solves that problem, but at a seemingly superficial level. Is that all there is to it -- change verbs to adjectives?
If instead I use POST to retrieve the editable version, then how do I distinguish between the POST that initially retrieves it, vs the POST that saves it? My (weak) excuse for using POST would be that retrieving an editable version would cause a change of state on the server: locking the resource. But that only holds if my requirements are to implement such a lock, which is not always the case. PUT fails for the same reason, plus PUT is not enabled by default on the Web servers I'm running, so there are practical reasons not to use it (and DELETE).
Note that even in the editable state, I haven't made any changes yet; presumably when I submit the resource to the Web server again, I'd POST it. But to get something that I can later POST, the server has to first serve up a particular representation.
I guess another approach would be to have separate resources at the collection level:
GET /read-only/resource/<id> and GET /editable/resource/<id> or GET /resource/read-only/<id> and GET /resource/editable/<id> ... but that looks pretty ugly to me.
Thoughts?
1) It is perfectly valid to have two distinct resources, one for viewing and one for editing some domain concept. Just be aware that because they are two different URIs from REST's perspective they are two different resources. Too often people conflate resource with domain object. That's why they end up being stuck only doing CRUD.
2) Don't get too hung up on the name of the resource. The important thing is that you realize that what the URI points to is a "thing", "a resource". If that's more obvious to you with editable instead of edit then use that. Having a verb in your URL doesn't make your application wrong, it just makes it a bit less readable to the human developer. Using a verb in the URL to try and redefine the semantics of the HTTP method, now that's a violation of the uniform interface constraint.
In REST, editing an existing resource is accomplished by a client GET-ing a representation of that resource, making changes to the representation, and then doing a PUT of the new representation back to the server.
So to just read a resource your REST client program would do a:
GET http://www.example.com/SomeResource
And to edit that resource:
GET http://www.example.com/SomeResource
... edit it ...
PUT http://www.example.com/SomeResource
Normally simultaneous updates are handled by letting the last PUT arriving at the server overwrite the earlier ones, on the assumption that it represents a newer state. But in your case you want to guard against this.
Carefully consider #Jason's suggestion to maintain an optional parallel lock resource for each main resource. Your client would first create the lock, do the edit, then delete the lock. Your system would need to release a lock automatically if the user making the lock subsequently never saves any changes. This would look like:
GET http://www.example.com/SomeResource
... user presses an edit button ...
PUT http://www.example.com/SomeResource/lock
... user edits the resource's representation ...
PUT http://www.example.com/SomeResource
DELETE http://www.example.com/SomeResource/lock
You'd need to do some appropriate error handling if the user is trying to edit a resource that's locked by someone else.
It sounds like you feel you're constrained by the current limitations of HTML. If you use a server-side REST framework like Restlet (for Java), it supports the notion of "overloaded POST", where you can use POST but tack on a query string argument like method=PUT or method=DELETE. If you're writing your own server-side components they can use this trick too.
There are tricks you can play at the HTML level too. For instance your page can have a read-only part that's initially displayed, and an input form that's initially not shown. When the user presses the edit button, your JavaScript hides the read-only part and shows the input form.
Be sure to read Richardson and Ruby's Restful Web Services (O'Reilly) too. It's extremely helpful.
I don't think returning a form or just values is up to a REST server, but the responsibility of the client. Whether a resource is editable is a property of the resource, and not something defined by the URL.
In other words: The URL for getting the resource is GET /resource/<id>. This has a property editable. If a user wants a form it can retrieve the resource from the same URL and populate the form. The client can than PUT/POST changes.
How do I construct a URL to get the read-only or editable version?
There's an underlying problem here, which is that you are constructing URLs in the first place - appending IDs to hard-coded URLs is not REST. Roy Fielding has written about this very mistake. Whichever document prompts you to edit the resource should contain the URI to the editable variant of that resource. You follow that URI, whether that's /resource/editable or /editable/resource is outside the scope of REST.
If instead I use POST to retrieve the editable version, then how do I distinguish between the POST that initially retrieves it, vs the POST that saves it?
You perform a GET (not a POST) to read the resource, and POST (or PUT) to write the resource.
If you want to create a lock on the resource in question, use POST to write to the resource (or the resource's container, with the resource ID encoded in the body of the POST), and have the server create a lock as a new resource, and return an ID of that resource as the response to the POST. (with authentication issues beyond the scope of your question or this answer)
Then to unlock the lock, either use a DELETE on the lock resource, or POST to the lock's container.
I guess your question could be "how to identify the readonly representation that return with GET action in PUT action?". You could do this:
<Root>
<readonly>
<p1><p1>
...
<readonly>
<others>
...
<others>
<Root>
After parsing the request XML from PUT you can ignore the readonly part and process others. In Response, return 200 status and leave a message saying the part in readonly is ignored.
Is it your expected?

Resources