HydraCG / Specifications

Specifications created by the Hydra W3C Community Group
Other
139 stars 25 forks source link

Nested structures (supportedProperty) #26

Open lanthaler opened 10 years ago

lanthaler commented 10 years ago

Sam Goto raised concerns about the complexity of nested structures. We need to reduce the verbosity of operations expecting nested structures in which some of the properties in nested objects have, e.g., to be marked as required.

Actions in Gmail currently uses property paths to express such things:

<script type="application/ld+json">
{
  "@context": "http://schema.org",
  "@type": "EmailMessage",
  "description": "We hope you enjoyed your meal at Joe's Diner. Please rate your experience.",
  "action": {
    "@type": "ReviewAction",
    "review": {
      "@type": "Review",
      "itemReviewed": {
        "@type": "FoodEstablishment",
        "name": "Joe's Diner"
      },
      "reviewRating": {
        "@type": "Rating",
        "bestRating": "5",
        "worstRating": "1"
      }
    },
    "handler": {
      "@type": "HttpActionHandler",
      "url": "http://reviews.com/review?id=123",
      "requiredProperty": {
        "@type": "Property",
        "name": "review.reviewRating.ratingValue"       <--- PROPERTY PATH
      },
      "method": "http://schema.org/HttpRequestMethod/POST"
    }
  }
}
</script>
lanthaler commented 10 years ago

_Markus' reply to Sam's mail:_

Let's use the review example as it is fairly compact. In your examples above you currently use something like this (I slightly simplified it and added a required: true):

{
  ...
  "operation": {
    "@type": "ReviewAction",
    "expects": {
      "supportedProperty": [
        {
          "property": "http://schema.org/reviewBody",
          "required": true
        }
        {
          "property": "http://schema.org/reviewRating",
          "required": true
          "rangeIncludes": {
            "subClassOf": "Rating",
            "supportedProperty": {
              "property": http://schema.org/ratingValue",
              "required": true
            }
          }
        }
      ]
    }
  }
}

This describes the following structure:

http://schema.org/reviewBody - required
http://schema.org/reviewRating - required
    (subClassOf: Rating)
    http://schema.org/ratingValue - required

So we either have to replicate that nesting or flatten it somehow.

One option we already discussed it is to avoid the class/supportedProperty indirection and instead point directly to properties. In this case it wouldn't help much as the nested property is nested inside a rangeIncludes.

{
  ...
  "operation": {
    "@type": "ReviewAction",
    "expects": [
      {
        "property": "http://schema.org/reviewBody",
        "required": true
      }
      {
        "property": "http://schema.org/reviewRating",
        "required": true
        "rangeIncludes": {
          "subClassOf": "Rating",
          "supportedProperty": {
            "property": http://schema.org/ratingValue",
            "required": true
          }
        }
      }
    ]
  }
}

Thus, in order to simplify it we probably need to use something else than "rangeIncludes". We could perhaps reuse "supportedProperty" but that would make the data difficult to understand IMO. In lack of a better name, I used "supportedRange" below and allow its value to be either a Property, a SupportedProperty or a Class.

{
  "@context": "http://schema.org",
  "@id": "http://code.sgo.to/products/123",
  "@type": "Product",
  "name": "A product that can be reviewed",
  "operation": {
    "@type": "ReviewAction",
    "expects": [
      {
        "property": "http://schema.org/reviewBody",
        "required": true
      }
      {
        "property": "http://schema.org/reviewRating",
        "required": true
        "supportedRange": {
          "property": http://schema.org/ratingValue",
          "required": true
        }
      }
    ]
  }
}

This does indeed simplify the description. The nesting corresponds 1:1 to the "abstract nesting":

http://schema.org/reviewBody - required
http://schema.org/reviewRating - required
    http://schema.org/ratingValue - required

In that sense, it's optimal. Now if really necessary, we could try to flatten this representation but I don't know how much value that really provides. A trivial approach would be to specify the parent (in this case specifying the parent property, another option would be to give the SupportedProperty an identifier and use a reverse property for supportedRange to connect them):

{
  "@context": "http://schema.org",
  "@id": "http://code.sgo.to/products/123",
  "@type": "Product",
  "name": "A product that can be reviewed",
  "operation": {
    "@type": "ReviewAction",
    "expects": [
      {
        "property": "http://schema.org/reviewBody",
        "required": true
      }
      {
        "property": "http://schema.org/reviewRating",
        "required": true
      },
      {
        "property": http://schema.org/ratingValue",
        "required": true,
        "parent": "http://schema.org/reviewRating"
      }
    ]
  }
}

I find this flattening quite confusing and counterintuitive. If there are nested properties, I think it's reasonable to have the same nesting in the descriptions thereof.

What do you think about this options Sam?

I have to say that I don't find the example using rangeIncludes too bad even though rangeIncludes (in contrast to rdfs:range) might be a bit counterintuitive when used with required properties as it suggests that these required properties are somehow nevertheless optional as there might be other valid ranges as well.

gkellogg commented 10 years ago

This, of course, invokes OWL restrictions for doing similar things; if Hydra is ultimately intended to be a W3C recommendation, then working smoothly with existing technologies would seem to make sense. However, Hydra also seems intended to influence schema.org, which is already inconsistent with OWL (e.g. rangeIncludes/domainIncludes), and so some approach that is more native or web-friendly also is worth pursuing.

Regarding property paths, @lanthaler's suggestion takes advantage of common JavaScript object navigation, but this does tie it vary closely to JSON. IMO, we should be wary of this and consider concepts which are not so bound to a format. For example, SPARQL property paths also provide a way of navigating through such object structures; this might be review/reviewRating/ratingValue. This approach could also allow for relative patching using ^.

lanthaler commented 10 years ago

This, of course, invokes OWL restrictions for doing similar things;

Gregg, would you mind explaining this on the mailing list (I would prefer to keep the discussion there as more people will be able to follow it)?

Regarding property paths, @lanthaler's suggestion takes advantage of common JavaScript object navigation, but this does tie it vary closely to JSON. IMO, we should be wary of this and consider concepts which are not so bound to a format.

Just for the record: this wasn't my suggestion. It is what Gmail uses today:

https://developers.google.com/gmail/actions/reference/review-action

I'm myself very concerned about this.

lanthaler commented 10 years ago

PROPOSAL: See proposal of ISSUE #37, it addresses this issue as well