- From: Markus Lanthaler <markus.lanthaler@gmx.net>
- Date: Mon, 21 Oct 2013 11:35:14 +0200
- To: "'Sam Goto'" <goto@google.com>
- Cc: <public-hydra@w3.org>, "'W3C Web Schemas Task Force'" <public-vocabs@w3.org>
On Saturday, October 19, 2013 3:19 AM, Sam Goto wrote: > > > For example, netflix can stream (http://schema.org/WatchAction) movies > > > (http://schema.org/Movie), but not *any* movie: it can stream a specific > > > set of movies that are in their *inventory* of streamable movies (e.g. > > > movies that in theatres right now are *not* in their inventory, movies > > > that can only be rented via DVDs either, etc). > > > > If there's a large number of instances which all support the same > > operations, it makes sense to create a separate class to communicate that > > information to the client. In the example above, that class could, e.g., be > > called StreamableMovie. The WatchAction can then simply be attached to that > > class. When talking to programmers without Semantic Web background I > > typically explain that in terms of interfaces an instance implements or > > inheritance similar to what they know from their object oriented programming > > languages. > > Although this is in the right direction, we found it to be slightly trickier > than that. One example is that Netflix and Hulu may have StreamableMovie on > their inventories, *but* Netflix/Hulu may only play the StreamableMovies on > *their* inventories. > > So, you need to get deeper into the constraint and add that Netflix can play > movies that (a) needs to be a StreamableMovie but as well as (b) it needs to > have url = "netflix.com" for instance. So basically you are saying you get the information about the movie somewhere else, right? In my description I was assuming you are browsing through Netflix' API and get the StreamableMovies there. Netflix obviously know whether their movie is streamable or not. I think we are talking about slightly different use cases or at least solutions. > One direction we are exploring (which adds a *lot* of complexity), is having > some sort of constraint/restriction Type that could express these > constraints. Here is one example of such a thing. Hmmm... this may work very well within a *single* API but I can't see how such an approach should work across the Web. > > If the operations/actions that the various resources of a Web API offer > > widely, it often makes more sense to attach the operations directly to the > > instance instead of binding it to a class. Hydra supports that via its > > "operations" property: > > > > { > > "@context": "http://purl.org/hydra/core/context.jsonld", > > "@id": "/a-movie", > > "title": "A streamable movie", > > "operations": [ > > { > > "@type": "http://schema.org/WatchAction", > > "method": ... > > ... > > } > > ] > > } > > Yep, that's another direction we are exploring. We are exploring adding one > property to http://schema.org/Thing called potentialAction (or operation, > exact name TBD) that does the mapping to the action that can be taken on a > specific Thing instance. > > Here is where we explored this idea. > > Basically, instead of expressing the map of action -> entities, we instead > ask publishers/developers to expose the reverse map of entity -> actions and > we then crawl and build the reverse index. This sounds as you would like to build something similar to actions in GMail, is that correct? Or why else do you suggest to "prefer" actions over entities? > Here is an example: > > <script type="application/ld+json"> > { > "@context": "http://schema.org", > "@type": "Movie", > "url": "http://movies.netflix.com/WiMovie/Like_Crazy/70167118", > "operation": { > "@type": "WatchAction" > "status": "proposed", > "handler" : { > "@type": "WebPageHandler", > "url": "http://movies.netflix.com/WiPlayer?movieid=70167118&trkid=1464504&t=Like+Cr azy", > "method": "GET", > } > } > </script> Wouldn't this specific example be much simpler if you would introduce a specialized property as I suggested in my last mail [1]? Something like: { "@context": "http://schema.org", "@id": "http://movies.example.com/Like_Crazy", "@type": "Movie", "stream": [ "http://movies.netflix.com/WiPlayer?movieid=70167118&trkid=1464504", "http://hulu.com/89089409840650440", ] } It would of course also be possible to use objects instead of just URLs in "stream" to convey more information (e.g. price, provider etc.): { "@id: "http://hulu.com/89089409840650440", "provider": "http://hulu.com", "subscriptionReqired": true, ... } > I think you got the general idea of the options we are exploring. > > I think the entity -> actions mapping is fairly clear and solves a huge > number of problems. Agreed > We still think we need the action -> entities mapping too, we'd love any > input you may have in that area. We explored things like resource shapes, > sparql ask queries and prototype languages. Hmm... since you were speaking about crawling and creating inverse indexes before, why do you think you need it? Let's try to talk about more concrete use cases. I suspect one use case you might be interested to address is that a user gets an email about an event. You would then like to create a user interface which allows the user to book a ticket for that event. So you need to find APIs (actions) that allow you to do that. You could either try to describe the actions as accurate as possible (the action accepts Events, that are in a specific region, maybe organized by some specific organizer etc.) or you try to find the corresponding event entity by crawling the API. I think the latter is much simpler to achieve. Say the user gets a mail about Lady Gaga's concert in two weeks. You would then need to have an index of APIs that allow you to book tickets for that event. You already crawl event sites, why can't you just do the same for APIs? It's then a matter of ensuring that the found events match the one the user looks for. You then have a lot of entries in the following shape: { "@id": "http://example.com/event4680", "@type": "Event", "name": "Lady Gaga live in concert", ... "offers": [ { "@id": "http://example.com/event4680/398", "@type": "Offer", "name": "General Admission Ticket", "price": "89", "priceCurrency": "USD" "operations": { "@type": "BuyAction", "method": "POST", "expects": "http://example.com/vocab/OrderDetails" } }, ... ] } Don't you think such an approach would be much simpler and work in 99% of the cases? > Here are a few examples (none of which we are particularly excited about): > > Resource shapes: > > <script type="application/ld+json"> > { > "@context": "http://schema.org", > "@type": "WatchAction" > "status": "proposed", > "object/restriction" : { > "@type": "DataTypeRestriction", > "describes": "http://schema.org/Movie", > "property" : { > "property": "http://schema.org/url", > "pattern": "http://movies.netflix.com/Movie/", > } > "property" : { > "property": "http://schema.org/streameable", > "allowedValue": "true", > } > }, > "handler" : { > "@type": "ActionHandler", > "url": "http://www.netflix.com/watch", > } > } > </script> > > > SPARQL > > > <script type="application/ld+json"> > { > "@context": "http://schema.org", > "@id": "SFRestaurant" > "@type": "Type", > "name": "SF Restaurant", > "restriction": { > "@type": "DatatypeRestriction" { > "sparql": "SELECT ?r WHERE {?r <http://schema.org/address> > [<http://schema.org/addressLocality> 'SF']}" > } > } > } > </script> Again, while I think these might be a great solution for internal APIs, I don't think they would work (and scale) if used across the whole Web. In such a case, I think a radically simpler approach such as Hydra's expects mechanism gives you almost the same the functionality with considerably less complexity. I believe it's too complex (close to impossible) to express the restrictions in a generic manner since in most cases it not only depends on the entity-action relationship but also on the relationship between the user trying to invoke the action and the API publisher offering it. So questions like whether the user has a Hulu account.. if so, which one.. where the user is located etc. Cheers, Markus [1] http://lists.w3.org/Archives/Public/public-hydra/2013Oct/0025.html -- Markus Lanthaler @markuslanthaler
Received on Monday, 21 October 2013 09:35:47 UTC