Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How should list ordering be preserved in R5? #76

Closed
dbooth-boston opened this issue Feb 19, 2020 · 22 comments
Closed

How should list ordering be preserved in R5? #76

dbooth-boston opened this issue Feb 19, 2020 · 22 comments

Comments

@dbooth-boston
Copy link
Contributor

dbooth-boston commented Feb 19, 2020

FHIR requires that item order be preserved in lists, but native RDF list support is terrible. How should FHIR RDF retain item ordering when a list is given?

Example JSON:

{
  "resourceType": "Patient",
  "id": "example",
  "name": [              # Outer list
    {
      "family": "Chalmers",
      "given": [           # Inner list
        "Peter",
        "James"
      ]
    }
  ]
}

Option 0: Do nothing. Keep the R4 representation, which uses fhir:index to indicate the relative ordering of items in a list.

Example Turtle:

ex:example a  fhir:Patient ;
    fhir:Resource.id  [ fhir:value  "example"  ] ;
    fhir:Patient.name  [        # Outer list item
        fhir:index  0
        fhir:HumanName.family  [ fhir:value  "Chalmers"  ] ;
        fhir:HumanName.given  [ # Inner list item
            fhir:index  1  ;
            fhir:value  "James"  ] ;
        fhir:HumanName.given  [ # Inner list item
            fhir:index  0  ;
            fhir:value  "Peter"  ] ;
        ] .

Note that if bnode and fhir:value are removed, per issue 77 option 3b, then fhir:value would still be needed for primitive list items, to attach the fhir:index:

ex:example a  fhir:Patient ;
    fhir:Resource.id  "example" ;
    fhir:Patient.name  [        # Outer list item
        fhir:index  0
        fhir:HumanName.family "Chalmers" ;
        fhir:HumanName.given  [ # Inner list item
            fhir:index  1  ;
            fhir:value  "James"  ] ;
        fhir:HumanName.given  [ # Inner list item
            fhir:index  0  ;
            fhir:value  "Peter"  ] ;
        ] .

Option 1: Set with parallel RDF list. See https://github.com/fhircat/fhir_rdf_validator/blob/master/tutorial/FHIRR5.md In this option, each JSON list is represented in RDF both as an unordered set of values and as an RDF list. Note that in this example, the outer set has only one item, so when it is repeated as a list, it looks almost identical.

Example Turtle:

ex:example a  fhir:Patient ;
    fhir:Resource.id  [ fhir:value  "example"  ] ;
    fhir:Patient.name  [                            # Outer set item
        fhir:HumanName.family  [ fhir:value  "Chalmers"  ] ;
        fhir:HumanName.given "James" ;              # Inner set item
        fhir:HumanName.given "Peter" ;              # Inner set item
        fhir:HumanName.given ( "James" "Peter" ) ;  # Inner list
        ] ;
    fhir:Patient.name  ( [      # Outer list
        fhir:HumanName.family  [ fhir:value  "Chalmers"  ] ;
        fhir:HumanName.given "James" ;              # Inner set item
        fhir:HumanName.given "Peter" ;              # Inner set item
        fhir:HumanName.given ( "James" "Peter" ) ;  # Inner list
        ] ) .

Pros:

  • Easy to JSON-RDF converter to implement, using existing JSON-LD order list mechanism.
  • Avoids choosing a list representation having an explicit index.

Cons:

  • Nobody wants to use conventional RDF lists.
  • The range of fhir:HumanName.given becomes both primitive values and a list.
@dbooth-boston
Copy link
Contributor Author

dbooth-boston commented Feb 20, 2020

List ordering option 2: parallel explicit index list. Similar to option 1, but using an explicit index using OLO or other conventions instead of a standard RDF list.

# Option 2: Similar to option 1, but using OLO.
ex:example a  fhir:Patient ;
    fhir:Resource.id  [ fhir:value  "example"  ] ;
    fhir:Patient.name  [                            # Outer set item
        fhir:HumanName.family  [ fhir:value  "Chalmers"  ] ;
        fhir:HumanName.given "James" ;              # Inner set item
        fhir:HumanName.given "Peter" ;              # Inner set item
        fhir:HumanName.given [                      # Inner list
            a olo:OrderedList ;
            olo:slot [ olo:index 1 ; olo:item "James" ] ;
            olo:slot [ olo:index 2 ; olo:item "Peter" ] ;
            ]
        ] ;
    fhir:Patient.name  [        # Outer list
        a olo:OrderedList ;
        olo:slot [
            fhir:HumanName.family  [ fhir:value  "Chalmers"  ] ;
            fhir:HumanName.given "James" ;              # Inner set item
            fhir:HumanName.given "Peter" ;              # Inner set item
            fhir:HumanName.given [                      # Inner list
                a olo:OrderedList ;
                olo:slot [ olo:index 1 ; olo:item "James" ] ;
                olo:slot [ olo:index 2 ; olo:item "Peter" ] ;
                ]
            ]
        ] . 

Pros:

  • Better for RDF users than option 1?

Cons:

  • Ugh. Verbose!
  • We have to choose a list convention.
  • Requires custom handling in the JSON->RDF converter.
  • Like with option 1 the range of fhir:HumanName.given becomes both primitive values and a list.

schema.org uses an explicit 1-based position property:

@dbooth-boston
Copy link
Contributor Author

dbooth-boston commented Feb 20, 2020

List ordering option 3: Only use regular RDF lists

This example assumes that we also change to eliminate the extra bnode and fhir:value, per issue #77 option 3b.

ex:example a  fhir:Patient ;
    fhir:Resource.id  [ fhir:value  "example"  ] ;
    fhir:Patient.name  ( [                          # Outer list 
        fhir:HumanName.family "Chalmers" ;
        fhir:HumanName.given ( "James" "Peter" ) ;  # Inner list
        ] ) .

@dbooth-boston
Copy link
Contributor Author

dbooth-boston commented Feb 20, 2020

List ordering option 4: parallel indexed list, but using a separate attribute. Similar to option 1, but instead of putting the parallel index list under the same attribute, put it under an ordered attribute. This would be analogous to extension option 1 (Put extensions under a sibling extension property: https://github.com/fhircat/FHIRCat/issues/31#issuecomment-589277765

ex:example a  fhir:Patient ;
    fhir:Resource.id  [ fhir:value  "example"  ] ;
    fhir:Patient.name  [                            # Outer set item
        fhir:HumanName.family  [ fhir:value  "Chalmers"  ] ;
        fhir:HumanName.given "James" ;              # Inner set item
        fhir:HumanName.given "Peter" ;              # Inner set item
        fhir:HumanName.givenList ( "James" "Peter" ) ;  # Inner list
        ] ;
    fhir:Patient.nameList  ( [  # Outer list
        fhir:HumanName.family  [ fhir:value  "Chalmers"  ] ;
        fhir:HumanName.given "James" ;              # Inner set item
        fhir:HumanName.given "Peter" ;              # Inner set item
        fhir:HumanName.givenList ( "James" "Peter" ) ;  # Inner list
        ] ) .

Pros:

  • Disambiguates the fhir:HumanName.given property

Cons:

  • In theory, fhir:HumanName.givenList could clash with another FHIR property of the same name.

@dbooth-boston dbooth-boston transferred this issue from fhircat/FHIRCat Nov 2, 2020
@balhoff
Copy link
Contributor

balhoff commented Oct 21, 2021

Discussion on call on 2021-10-21:

  • None in favor of using native RDF lists (option 1).
    • Too difficult to make use of list indices for ordering SPARQL results.
  • Agree that option 2: parallel explicit index list implies a list structure that is much the same as the current R4 model. An alternative version of option 2 would be:
    • Retain R4 structure but add redundant "direct" triples (option 5?).

An open question is whether the redundant information is worth it in this case, given that the indexed version will always be present.

Todo: Ensure that it is explicitly stated somewhere that the indexes need to be in sequence, starting from 0 (in the event this applies to the selected model).

@dbooth-boston
Copy link
Contributor Author

@balhoff
Copy link
Contributor

balhoff commented Dec 15, 2021

In the last meeting, we discussed whether using native RDF lists would interfere with treating the RDF rendering as an OWL document. I think that may be the case: the OWL 2 Web Ontology Language
Structural Specification and Functional-Style Syntax
says:

  • Section 2.4: "IRIs with prefixes rdf:, rdfs:, xsd:, and owl: constitute the reserved vocabulary of OWL 2. As described in the following sections, the IRIs from the reserved vocabulary that are listed in Table 3 have special treatment in OWL 2."
  • Section 5.3 "IRIs from the reserved vocabulary other than owl:topObjectProperty and owl:bottomObjectProperty must not be used to identify object properties in an OWL 2 DL ontology."

In order to use an OWL reasoner on the contents of lists we would need to treat rdf:first and rdf:rest as object properties.

@balhoff
Copy link
Contributor

balhoff commented Feb 24, 2022

@csisc
Copy link

csisc commented Jul 29, 2022

Just a side proposal: What do you think of using rdf:bag and rdf:seq.

@csisc
Copy link

csisc commented Jul 29, 2022

As a medical student, I probably should evocate the significance of order in certain situations.

@csisc
Copy link

csisc commented Jul 29, 2022

Symptoms can change their characteristics according to the evolution of the condition:

  • Acute appendicitis: epigastric pain (visceral) that is present early in the course of the disease is replaced with right lower quadrant (somatic) pain later in the illness.
  • Acute cholangitis: Charcot's cholangitis triad implies that pain comes first followed by fever and finally by jaundice.

@dbooth-boston
Copy link
Contributor Author

Just a side proposal: What do you think of using rdf:bag and rdf:seq.

That could be a possibility in theory, but the motivation behind this issue is to enable conventional RDF lists (a/k/a RDF Collections) to be used in FHIR RDF, using the Turtle short-hand syntax.

@dbooth-boston
Copy link
Contributor Author

Symptoms can change their characteristics according to the evolution of the condition: . . .

Yes, the order of events is crucial in healthcare. However, from what I've seen, most of the time-ordered events that are recorded in medical records have individual timestamps on them anyway -- allowing them to be unambiguously ordered -- so they are usually stored as separate events rather than storing them as a list per se. However, some properties allow a list of entries to be provided -- such as a patient contact or address -- and the order of items in the list is sometimes used to indicate precedence.

@ericprud
Copy link
Member

Just a side proposal: What do you think of using rdf:bag and rdf:seq.

I don't think that helps. The prob is not the first/rest ladder, but instead the expression of axioms on properties in the rdf: namespace. I think we have to roll our own property.

@dbooth-boston
Copy link
Contributor Author

Discussed on 04-Aug-2022, 09-Aug-2022, 11-Aug-2022

@dbooth-boston
Copy link
Contributor Author

dbooth-boston commented Aug 16, 2022

To summarize my view, I think we'd be losing more than we're gaining by switching to RDF lists, because:

  1. They don't play well with OWL
  2. They don't play well with SPARQL
  3. They don't add much syntactic benefit, because elements in FHIR lists are always complex objects anyway, so the list syntax gets visually lost. The only visual clue is the lack of semicolons between items. See example below.
  4. We don't have RDF lists in R4, so there would be less change to R5.

Example JSON:

##### Example exJson:
      "coding": [
        {
          "system": "http://terminology.hl7.org/CodeSystem/v3-ObservationInterpretation",
          "code": "H",
          "display": "High"
        },
        {
          "system": "http://example.com/Observation",
          "code": "Hi",
          "display": "High"
        },
        {
          "system": "http://example.orgObs",
          "code": "H",
          "display": "Highest"
        }

With RDF lists:

##### Example exWithListsTurtle
... fhir:coding (
        [
          a <http://terminology.hl7.org/CodeSystem/v3-ObservationInterpretation/H>;
          fhir:system [
            notrdf:value "http://terminology.hl7.org/CodeSystem/v3-ObservationInterpretation"^^xsd:anyURI
          ];
          fhir:code [
            notrdf:value "H"
          ];
          fhir:display [
            notrdf:value "High"
          ]
        ]
        [
          a <http://example.com/Observation/Hi>;
          fhir:system [
            notrdf:value "http://example.com/Observation"^^xsd:anyURI
          ];
          fhir:code [
            notrdf:value "Hi"
          ];
          fhir:display [
            notrdf:value "High"
          ]
        ]
        [
          a <http://example.orgObs/H>;
          fhir:system [
            notrdf:value "http://example.orgObs"^^xsd:anyURI
          ];
          fhir:code [
            notrdf:value "H"
          ];
          fhir:display [
            notrdf:value "Highest"
          ]
        ]
      )

Without RDF lists:

##### Example exWithoutListsTurtle
... fhir:coding [
      a <http://terminology.hl7.org/CodeSystem/v3-ObservationInterpretation/H>;
      fhir:system [
        notrdf:value "http://terminology.hl7.org/CodeSystem/v3-ObservationInterpretation"^^xsd:anyURI
      ];
      fhir:code [
        notrdf:value "H"
      ];
      fhir:display [
        notrdf:value "High"
      ];
      fhir:index 0
    ], [
      a <http://example.com/Observation/Hi>;
      fhir:system [
        notrdf:value "http://example.com/Observation"^^xsd:anyURI
      ];
      fhir:code [
        notrdf:value "Hi"
      ];
      fhir:display [
        notrdf:value "High"
      ];
      fhir:index 1
    ], [
      a <http://example.orgObs/H>;
      fhir:system [
        notrdf:value "http://example.orgObs"^^xsd:anyURI
      ];
      fhir:code [
        notrdf:value "H"
      ];
      fhir:display [
        notrdf:value "Highest"
      ];
      fhir:index 2
    ];

@csisc
Copy link

csisc commented Aug 16, 2022

I have seen the W3C discussions. I found https://lists.w3.org/Archives/Public/public-owl-wg/2008Jun/0070.html as a solution.

@csisc
Copy link

csisc commented Aug 16, 2022

To explain the proposal, there are slides proposed by Drummond at https://protege.stanford.edu/conference/2006/submissions/slides/7.1_Drummond.pdf. Please see the part about OWL lists.

@dbooth-boston
Copy link
Contributor Author

Thanks, @csisc , for finding that. David Wood and James Leigh also made a proposal at the 2009 W3C RDF Next Steps workshop to add ordered lists to RDF as a fundamental concept, instead of the makeshift first/rest ladder that RDF currently has for them. I personally think that ordered lists should be a fundamental concept in RDF, rather than continuing to try to retrofit onto a first/rest ladder. It is a blatant gap in RDF. To quote Manu Sporny (inventor of JSON-LD):

RDF is a shitty data model. It doesn’t have native support for lists. LISTS for fuck’s sake! The key data structure that’s used by almost every programmer on this planet and RDF starts out by giving developers a big fat middle finger in that area.

But I think RDF lists as a built-in type will have to wait until RDF 2.0. :)

@dbooth-boston
Copy link
Contributor Author

On today's call we reached consensus to go ahead with RDF lists in R5:

AGREED: Adopt RDF lists

@dbooth-boston
Copy link
Contributor Author

Done in R5.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants