Re: Interpretation of POST operation given large relationship collections

On Oct 14, 2014, at 1:07 PM, John Walker <john.walker@semaku.com> wrote:

> Hi Gregg,
>  
>  
>> On October 14, 2014 at 8:32 PM Gregg Kellogg <gregg@greggkellogg.net> wrote: 
>> 
>> On Oct 14, 2014, at 5:34 AM, John Walker < john.walker@semaku.com> wrote: 
>> 
>>> Hi Gregg
>>> 
>>> > On October 12, 2014 at 9:36 PM Gregg Kellogg < gregg@greggkellogg.net> wrote: 
>>> > 
>>> > 
>>> > The primary (only?) way of updating a Hydra resource is through an operation using the POST method. This would seem to have some small conflict with the use of hydra:Collection to manage resources having a potentially large number of relationships. 
>>> > 
>>> > Imagine an entity such as a Movie, with a large number of reviews. It might be reasonable to manage the reviews through a paged collection, due to the potential for a very large number of such reviews: 
>>> > 
>>> > <GoneGirl> a schema:Move; 
>>> > schema:name "Gone Girl"; 
>>> > hydra:hasCollection <GoneGirl/reviews> . 
>>> > <GoneGirl/reviews> a schema:PagedCollection; 
>>> > hydra:manages [hydra:subject <GoneGirl>; hydra:property schema:review ] 
>>> >
>>>  
>>> I was attempting to work my way through an example like this using SKOS instead on Schema.org [1].
>>> Following best SemWeb practices I had modeled the entity and the information about it as separate resources, in your example that might be:
>>>  
>>> <GoneGirl> a hydra:Resource ;
>>>   foaf:primaryTopic <GoneGirl#id> .
>>> <GoneGirl#id> a schema:Movie ;
>>>   schem:name "Gone Girl" ;
>>>   hydra:collection <GoneGirl/reviews> .
>>> <GoneGirl/reviews> a hydra:PagedCollection ;
>>>   hydra:manages [hydra:subject <GoneGirl#id> ; hydra:property schema:review ] .
>>>  
>>> > schema:Movie would be extended as a hydra:Class, with schema:review as a supportedProperty. schema:review would also be a hydra:Link. Using the existing SupportedProperty, this might look like the following: 
>>> > 
>>> > schema:Movie a hydra:Class; 
>>> > hydra:supportedProperty [ 
>>> > a hydra:SupportedProperty; 
>>> > hydra:property schema:review; 
>>> > hydra:readonly false; 
>>> > hydra:writeonly false 
>>> > ]; 
>>> > hydra:supportedOperation [ 
>>> > a hydra:Operation; 
>>> > hydra:method "POST"; 
>>> > hydra:expects schema:Movie; 
>>> > hydra:returns schema:Movie 
>>> > ] . 
>>> > 
>>> > A client has know way to know that schema:review is managed by a collection without retrieving the resource (fine). From an RDF perspective, the schema:review triples all have the same subject <GoneGirl> pointing to different reviews. When I retrieve the resource, I don't get all these reviews, even if I indirect through the paged collection, maintaining all triples referencing the review could take a fair amount of space. 
>>> > 
>>> > The point of the question is, what is the interpretation of POST? Does it replace all the triples having the same subject (presumably including referenced/referenced resources having a BNode subject including those managed through a collection? Does it exclude resources managed by a collection? What about if there is a propertyPath specifying the subject resource using a reverse relationship? 
>>> >
>>>  
>>> I'd expect that a POST on <GoneGirl> would append any triples in the request body to the <GoneGirl> resource, but perhaps a PUT would better apply here to replace the resource with the request body?   
>>  
>> I guess the spec needs to be clear about this. From normal REST practices a PUT would replace a resource representation, a PATCH might amend portions of it, and a POST would create a new one. My assumption would be that POSTing to an existing resource would return a 409 Conflict, as a POST is typically considered a Create operation, and attempting to create a previously existing resource could be considered an error.
>>  
> The append behaviour was based on how POST works in SPARQL 1.1 GSP, but that doesn't really fit in this context.
> 
LDP seem to use POST as Create rather than append too: https://dvcs.w3.org/hg/ldpwg/raw-file/default/ldp-primer/ldp-primer.html#creating-a-rdf-resource-post-an-rdf-resource-to-an-ldp-bc.
> So here we say it would only ever make sense to POST to a hydra:Collection resource right? Or is there any use case where we wouldn't pull the schema:Review instances out to separate resources and POSTing a review to the movie resource would embed the review in the representation of the schema:Movie? The latter doesn't sound like a good practice to me if I want to be able to DELETE the review, but that *could* also be achieved with a PATCH if the review is embedded.
> 
POSTing to an existing resource to create a subsidiary resource is not without precedent, but I'm not really a fan. Still, you might not have a collection managing a resource, but still want to add a subsidiary resource; this is likely the purpose of operations on properties in Hydra.
> Certainly can imagine if I GET a movie, would be nice to be able to pass a request parameter ?withReviews=Y to indicate I want to get the reviews embedded in the representation of the movie.
> 
This might be defined as a query operation on the Movie resource using an IriTemplate.

>>> If I wanted to add a new review, would I POST a representation of that review to the <GoneGirl> or <GoneGirl/reviews> resource? Personally would expect the latter in the case where a hydra:Collection is used.
>>  
>> I think the later too, if the POST also creates the Review. Posting to the collection implicitly associates the review with the movie and adds it to the collection.
>> 
>>> > Perhaps marking the property readonly: true would give sufficient information that the property can't be managed this way, and operations must be performed on the associated collection or using a LINK/UNLINK method on the resource? Otherwise, requiring the client to post all such relationships is unfeasible, and we have no other communication mechanism to say that they should/must be excluded from the resource representation when doing a POST. 
>>> >
>>>  
>>> In case where a hydra:Collection is used to manage the schema:Review list, I'd expect the schema:review property to not even be present in the <GoneGirl> resource.
>>  
>> Maybe, but if you were to simply look at vocabulary information you would see that schema:review is a property of schema:Movie. From a triples perspective, it is as well, as the collection manages Movie review Review triples, but it's not in the API, so it might just be not present, or marked readaable/writable=false. The later indicates that providing such a triple as part of the create/update operation on Movie is explicitly excluded, while the former doesn't really may any claim.
>>  
> I think this is partly where I am getting lost a bit. From a triples perspective I am quite happy if the triples with the same subject URI are actually spread over several dereferenceable Hydra resources. That might not be handy for a consumer, but as long as those resource reference each other (with rdfs:seeAlso for example) then I can follow my nose.
> 
> 
In my implementation, a GET of a primary resource returns all supported properties marked readable, so this would include triples with properties managed by a collection. A PUT or POST only accepts properties marked writable, also excluding those managed in a collection.
> Another area that is not 100% clear to me is what exactly I would get when I dereference the collection. Can imagine bare minimum would be:
> 
> <GoneGirl/reviews> a hydra:PagedCollection ;
>   hydra:manages [hydra:subject <GoneGirl> ; hydra:property schema:review ] ;
>   hydra:member <GoneGirl/reviews/review1> , <GoneGirl/reviews/review2> , <GoneGirl/reviews/review3> .
> 
> Or would I also include the following triples in the response:
> 
> <GoneGirl> schema:review <GoneGirl/reviews/review1> , <GoneGirl/reviews/review2> , <GoneGirl/reviews/review3> .
> 
> I guess I could also embed the reviews themselves in the response...
> 
That's how I interpret it; I also may include triples which reference the subject from the object (e.g., <GoneGirl/reviews/review1> reviewOf <GoneGirl>, hypothetically).

Gregg

>>> I'm wondering what I need to POST to the <GoneGirl/reviews> resource.
>>> As my new review has no identity yet, it'd be a blank node I assume.
>>>  
>>> _:b0 a schema:Review ;
>>>   schema:itemReviewed <GoneGirl> ; # or <GoneGirl#id>
>>>   schema:reviewBody "What a great film" ;
>>>   schema:reviewRating 5 .
>>  
>> My thinking too. The issue is with embedded resources also using blank nodes known which resource represents the subject of the POST. In my view, it is the subject who's type matches a range of the property associated with the collection.
> Makes sense, could also POST multiple reviews with this approach.
> 
> What about reviews of reviews ;P
> 
>>> Would I also need to explicitly include the triple linking the movie to the review:
>>>  
>>> <GoneGirl> schema:review _:b0 .
>>> # <GoneGirl#id> schema:review _:b0 .
>>  
>> Not necessary, I think, as it is implicit in posting to the collection managing that relationship.
>> 
>>> And/or the triple stating the review is a member of the collection:
>>>  
>>> <GoneGirl/reviews> hydra:member _:b0 .
>>>  
>>> Or is it reasonable to assume the server will add these?
>>  
>> I believe it is, but the spec should be clear on this.
>> 
>>> In the case of using LINK/UNLINK this would only be possible if the schema:Review already had an identitiy URI, so assume the client would have already had to POST it to some other generic <allReviews> collection.
>>  
>> Yes, you might imagine that a review is posted to a Movie, but a subsequent operation might want to make it a review of the actor's as well (better NewsArticle being about multiple things). This is where I was considering LINK/UNLINK.
>> 
>>> And I'm not sure how I would use LINK/UNLINK in the case that the movie used the hash URI pattern <GoneGirl#id>?
>>  
>> The hash URI can certainly be part of the link href. It may be up to server interpretation to associate the operation with the Movie vs. the Resource. It also may be that LINK/UNLINK operations aren't appropriate when using hash URIs. They could also be performed using something like a POST with a schema:AddAction or schema:DeleteAction on the collection; I find the minimalism of LINK/UNLINK verbs appealing, even though they're not quite standard yet.
> Agree on the minimalism (UN)LINK. With hash URIs it might also be worth to consider if/how that would work with fragment identifiers in HTML documents. I guess a PATCH could be used for this also.
> 
>  
> John
> 
>>  
>> Gregg
>> 
>>> > Thoughts? 
>>> > 
>>> > Gregg Kellogg 
>>> > gregg@greggkellogg.net 
>>> > 
>>> >
>>>  
>>> John
>>>  
>>> [1]  https://github.com/jaw111/skos-api
> 
>  

Received on Tuesday, 14 October 2014 20:36:00 UTC