W3C home > Mailing lists > Public > public-vocabs@w3.org > March 2014

Re: Nested structures / ISSUE-26 (was: An updated draft of the schema.org/Action proposal)

From: Sam Goto <goto@google.com>
Date: Mon, 3 Mar 2014 08:22:27 -0800
Message-ID: <CAMtUnc4ac9Vh+01eeNPrg1LV1Xo-2kgL5f-1UJoXjWvn9jpvcQ@mail.gmail.com>
To: Markus Lanthaler <markus.lanthaler@gmx.net>
Cc: W3C Web Schemas Task Force <public-vocabs@w3.org>, public-hydra@w3.org
On Fri, Feb 14, 2014 at 9:19 AM, Markus Lanthaler
<markus.lanthaler@gmx.net>wrote:

> On Friday, February 14, 2014 1:31 AM, Sam Goto wrote:
> >> 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 think that's a reasonable exploration of this approach. Just to keep
> > this as a fair/comprehensive comparison, lets look into what it would
> > look like "path-query-language" approach could look like*:
>
> Oh yeah, sorry. I didn't intend to sweep this under the table.
>
>
> > *majorly patterned after
> > https://developers.google.com/gmail/actions/reference/review-action
> >
> >   {
> >     "@context": "http://schema.org",
> >     "@id": "http://code.sgo.to/products/123",
> >     "@type": "Product",
> >     "name": "A product that can be reviewed",
> >     "operation": {
> >       "@type": "ReviewAction",
> >       "requiredProperties": [{
> >         "path": "reviewBody"
> >       }, {
> >         "path": "reviewRating.ratingValue"
> >       }]
> >     }
> >   }
> >
> > The "contents" of this payload is equivalent to:
> >
> >   http://schema.org/reviewBody - required
> >   http://schema.org/reviewRating - required (transitively inferred via
> > a sub-property being required too)
> >       http://schema.org/ratingValue - required
> >
> > Now, you can certainly formalize the path language to something like
> > SPARQL queries, XPATH/XSLT (yikes, I know) or the likes.
>
> Right, the simplest thing however, would probably be to just use an
> ordered list
>
>   {
>     "@context": {
>       "@vocab": "http://schema.org",
>       "path": { "@type": "@vocab", "@container": "@list"}
>     },
>     "@id": "http://code.sgo.to/products/123",
>     "@type": "Product",
>     "name": "A product that can be reviewed",
>     "operation": {
>       "@type": "ReviewAction",
>       "requiredProperties": [{
>         "path": [ "reviewBody" ]
>       }, {
>         "path": [ "reviewRating", "ratingValue" ]
>       }]
>     }
>   }
>
> That way, your JSON-LD processor would take care of the expansion of
> "reviewRating" etc. to full IRIs if desired.
>

Just as one more data point, it was just brought to my attention that RSDL
seems to be using this (i.e. the "review.reviewBody" approach) approach:

http://en.wikipedia.org/wiki/RSDL


>
>
>
> >> 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.
> >
> > Right. One of the advantages of SupportedClass is that it allows you
> > to link to to an external document. Take a look at the contents of
> > this doc (view:source and search for itemscopes): http://code.sgo.to/h
> > ttps+++developers.google.com.gmail+actions+reference+review-
> > action.html
>
> Exactly. I find that to be very powerful and still to be the cleanest
> approach, at least from a theoretical point of view. In my experience, it
> also makes it very easy to understand to most developers as you simply tell
> them that you just mark up (or separately serialize) exactly the same
> information they find in the documentation in a machine-processable way.
>
>
> > And how it can be used inline:
> >
> > http://code.sgo.to/crawler/yaap.html#url=http://code.sgo.to/products/123
>
> Another really cool demo. I hope it won't be too long till I myself again
> find the time to hack on prototypes.
>
>
> > That is, with linked data, the developer's code becomes quite
> > simpler/more concise (as you expose the expectations in external
> > docs):
> >
> >   {
> >     "@context": "http://schema.org",
> >     "@id": "http://code.sgo.to/products/123",
> >     "@type": "Product",
> >     "name": "A product that can be reviewed",
> >     "operation": {
> >       "@type": "ReviewAction",
> >       "expects": [
> >         {
> >           "@id": "
> http://code.sgo.to/https+++developers.google.com.gmail+actions+reference+review-action.html
> ",
> >         }
> >       ]
> >     }
> >   }
>
> If you set the @type of "expects" to @id in the context, you can even get
> rid of that @id-object and set the value directly to
> http://code.sgo.to/https+++...
>
> That being said, the code becomes really "fluid" as it is up to the
> developer to decide how much information he wants to embed inline and how
> much he prefers to reference externally.
>
>
> --
> Markus Lanthaler
> @markuslanthaler
>
>
>
Received on Monday, 3 March 2014 16:22:55 UTC

This archive was generated by hypermail 2.3.1 : Tuesday, 6 January 2015 21:29:37 UTC