Re: Reconciling hydra rest semantics for collections with typical RDF entity relationships

On Feb 4, 2014, at 10:26 AM, Markus Lanthaler <markus.lanthaler@gmx.net> wrote:

> Hi Gregg,
> 
> On Monday, February 03, 2014 11:24 PM, Gregg Kellogg wrote:
>> 
>> Excuse me for some random thoughts, but I've been reconciling using
>> Hydra for an API which typically returns JSON-LD representations of
>> entities described using schema.org. Similar issues may exist with the
>> schema.org action vocabulary as well. As a simple example, I may want
>> to express follows information for a Person. In Turtle, this might look
>> like the following:
>> 
>> <http://example/people/gregg> a schema:Person;
>>  schema:name "Gregg Kellogg"@en;
>>  schema:follows <http://example/people/markus>,
>> <http://example/people/kingsley> ...
>> 
>> However, given that the list of potentially people I follow could be
>> large; using Hydra I may construct this using a separate relationship
>> to a Collection:
>> 
>> <http://example/people/gregg> a schema:Person, :ApiPerson;
>>  :follows <http://example/people/gregg/follows> .
> 
> This is a general problem of RDF. AFAICT, there's no way general way to
> solve this issue for sets. If you would use a list, you could at least use
> the list's head node (which generally is a blank node). Remember our
> discussions in the JSON-LD group?
> 
> Both Schema.org with its ItemList and Hydra with its Collection take a
> rather pragmatic approach. We could of course go ahead and define a
> Collection's semantics so that
> 
>  x p c .
>  c hydra:members y .
> 
> would entail
> 
>  x p y .
> 
> which is what you are looking for, right?

That would be a way to do it with semantics, but I don't think this is as useful for the target audience. Also, I presumed that hydra:members would be an ordered collection (e.g., @container: @list), but that might not necessarily be the case; my examples had the values of hydra:members in a list, but this would be incompatible with such an entailment rule (sadly).

>> :ApiPerson a hydra:Class;
>>  hydra:supportedProperties [hydra:property schema:name],
>> [hydra:property :follows] .
>> 
>> :follows a hydra:Link
>>    rdfs:label "follows";
>>    rdfs:comment "Collection of followed people";
>>    rdfs:domain schema:Person;
>>    rdfs:range schema:Person;
> 
> This range isn't correct unless you want
> <http://example/people/gregg/follows> to be of type schema:Person.

Yes, it should be hydra:Collection. I supposed it could also be a sub-class of hydra:Collection where the range of hydra:member could be restricted to be schema:Person.

>>    hydra:supportedOperations [
>>      hydra:method "GET";
>>      hydra:returns hydra:Collection
>>  ] .
>> 
>> If the referenced collection contained the following data:
>> 
>> <http://example/people/gregg/follows> a hydra:Collection;
>>  hydra:members (<http://example/people/markus>
>> <http://example/kingsley> .
>> 
>> After loading both the original document and the collection into a
>> graph, I would now have the following:
>> 
>> <http://example/people/gregg> a schema:Person, :ApiPerson;
>>  :follows <http://example/people/gregg/follows> .
>> <http://example/people/gregg/follows> a hydra:Collection;
>>  hydra:members (<http://example/people/markus>
>> <http://example/kingsley> .
>> 
>> This now does not describe what I would want using the schema.org
>> definitions. One way to reconstruct what I want would be to add more
>> data to the collection document:
>> 
>> <http://example/people/gregg/follows> a hydra:Collection;
>>  hydra:members (<http://example/people/markus>
>> <http://example/kingsley> .
>> <http://example/people/gregg> schema:follows
>> <http://example/people/markus>, <http://example/people/kingsley> .
>> 
>> This is actually easier to do in JSON-LD:
>> 
>> {
>>  "@context": {
>>    "hydra": "http://www.w3.org/ns/hydra/core#",
>>    "schema": "http://schema.org/",
>>    "follower": {"@reverse": "schema:follows"}
>>  }
>>  "@id": "http://example/people/gregg/follows",
>>  "@type": "hydra:Collection",
>>  "members": [
>>    { "@id": "http://example/people/markus", "follower":
>> "http://example/people/gregg"},
>>    { "@id": "http://example/people/kingsley", "follower":
>> "http://example/people/gregg"}
>>  ]
>> }
> 
> That's the most straightforward solution I can think of.
> 
> 
>> The issue is better for single-valued properties, as the property value
>> would be the same as the entity identifier, which would result in what
>> you would expect when merging both entity definitions.
>> 
>> I guess the question is, is this an expected usage pattern? Should the
>> collection examples represent this, or should it be described as a
>> recommended practice? Perhaps I've missed something.
> 
> I think this is definitely one of the most common usage patterns in Web
> APIs. The question whether there needs to be a direct link between the
> resources or whether you can go "through" a Collection is another question.
> As long as the consumer of the data understands Collection/ItemList I think
> it's not a problem. If it doesn't, it is of course.

From an SEO perspective, it's not clear that schema.org partners would make this connection, even though a ItemList has been defined. For that to be the case, I would expect that they would allow any property to take an ItemList in addition to the specified property range and do the inference you suggested above.

> Maybe Ruben has something more to say about this.. N3 *might* allow a nicer
> solution but I think that's out of scope. Isn't it?

Yes, N3 also have inverse links, and it's been proposed for a Turtle follow-on, in order to better align with SPARQL. In this case, I don't think it really helps that much. (N3 also has "is x of" for inverse property relationships, e.g. "Gregg Kellogg" is foaf:name of <gregg> .) In any case, this isn't too helpful for describing this use case and N3 isn't a standard.

Thanks for the response, at least I know that my understanding of the issues doesn't seem to be that far off.

Gregg

> --
> Markus Lanthaler
> @markuslanthaler
> 
> 

Received on Tuesday, 4 February 2014 18:56:58 UTC