Closed lanthaler closed 5 years ago
As discussed on the email chain, an alternative would be a BNode with reverse relationship to the collection:
</GreggKellogg> a foaf:Person;
foaf:knows [is hydra:member of </GreggKellogg/colleagues>]
Alternatively, if we mint a hydra:isMemberOf property as the inverse of hydra:member:
</GreggKellogg> a foaf:Person;
foaf:knows [hydra:isMemberOf </GreggKellogg/colleagues>]
(JSON-LD and RDFa both have nice support for reversed properties, so creating such a property probably isn't necessary.
This ends up using the BNode as an existential quantifier for any member of the colleagues collection, so doesn't create anything which would be inconsistent. Dereferencing the is member of relation gets a collection (or possibly, paged collection), which doesn't assert that it is, itself, a colleague. After pulling in the collection, and performing RDFS entailment, you'd get the following:
</GreggKellogg> a foaf:Person;
foaf:knows
[a foaf:Person; is hydra:member of </GreggKellogg/colleagues>],
</MarkusLanthaler> .
<MarkusLanthaler> a foaf:Person .
These statements are entirely consistent, and the BNode is rather more easily ignored than a collection IRI. In JSON-LD, it could look like the following:
{
"@context": {
"foaf": "http://xmlns.com/foaf/0.1/",
"hydra": "<http://www.w3.org/ns/hydra/",
"memberOf": {"@reverse": "hydra:member"}
},
"@id" "GreggKellogg",
"foaf:knows": {"memberOf": "GreggKellogg/colleagues"}
}
It does mean that saying foaf:knows is a hydra:Link isn't sufficient, but saying hydra:isMemberOf is a hydra:Link would be, and wouldn't need to be asserted on any other property for an API to be able to perform reasonable dereferencing.
On Wednesday, March 19, 2014 10:44 PM, Gregg Kellogg wrote:
Vering in to N3 syntax (and changing vocabularies), for the moment, an alternative way of referencing a collection could be through a BNode:
</GreggKellogg> a foaf:Person; foaf:knows [is hydra:member of </GreggKellogg/colleagues>]
Alternatively, if we mint a hydra:isMemberOf property as the inverse of hydra:member:
a foaf:Person; foaf:knows [hydra:isMemberOf </GreggKellogg/colleagues>]
(JSON-LD and RDFa both have nice support for reversed properties, so creating such a property probably isn't necessary.
This ends up using the BNode as an existential quantifier for any member of the colleagues collection, so doesn't create anything which would be inconsistent. Dereferencing the is member of relation gets a collection (or possibly, paged collection), which doesn't assert that it is, itself, a colleague. After pulling in the collection, and performing RDFS entailment, you'd get the following:
a foaf:Person; foaf:knows [a foaf:Person; is hydra:member of </GreggKellogg/colleagues>], .
a foaf:Person .
Hmm... I think this is a bit too clever and still creates a triple that you don't want.
These statements are entirely consistent, and the BNode is rather more easily ignored than a collection IRI.
This is a case where we should look at LDP [1], as Paul suggested some time ago. LDP allow you to describe a "DirectContainer" (I find the naming quite confusing) as follows:
</GreggKellogg> a foaf:Person ;
foaf:knows </MarkusLanthaler> .
</GreggKellogg/friends> a ldp:DirectContainer;
dcterms:title "Gregg's friends";
ldp:membershipResource </GreggKellogg>;
ldp:hasMemberRelation foaf:knows;
ldp:contains </MarkusLanthaler> .
The problem I have with LDP is that it hardcodes the complete interaction model. It's also kind of tricky to "find" such a container. You have to traverse the graph along non-materialized, reverse properties which is not exactly straightforward IMHO.
In JSON-LD, it could look like the following:
{ "@context": { "foaf": "http://xmlns.com/foaf/0.1/", "hydra": "<http://www.w3.org/ns/hydra/", "memberOf": {"@reverse": "hydra:member"} }, "@id" "GreggKellogg", "foaf:knows": {"memberOf": "GreggKellogg/colleagues"} }
It does mean that saying foaf:knows is a hydra:Link isn't sufficient, but saying hydra:isMemberOf is a hydra:Link would be, and wouldn't need to be asserted on any other property for an API to be able to perform reasonable dereferencing.
While I don't really like the specific blank node solution you are proposing, I find the principle quite interesting. We could avoid the blank node, and thus a triple we don't want, entirely but just including a member of collection directly:
{
"@context": {
"foaf": "http://xmlns.com/foaf/0.1/",
"hydra": "http://www.w3.org/ns/hydra/core",
"memberOf": { "@reverse": "hydra:member" }
},
"@id" "GreggKellogg",
"foaf:knows": {
"@id": "MarkusLanthaler,
"memberOf": "GreggKellogg/colleagues"
}
}
WDYT?
Markus Lanthaler @markuslanthaler
(Almost) a duplicate of #33
For me, resolving this is pretty much my top priority. At this point, I think there are two basic solutions:
1) Use a separate collection property, which has some semantic relationship to the base property, where the range is specifically a collection. For example:
</gregg> a foaf:Person; :knowsCollection </gregg/knowsCollection> .
:knowsCollection :collectionPropertyFor foaf:knows .
Then the collection can reference each member and re-assert the relationship
</gregg/knowsCollection> a hydra:Collection;
hydra:member </markus> .
</gregg> foaf:knows </markus> .
2) In a separate email, @lanthaler described an alternate using an intermediate object, such as the following:
</gregg> a foaf:Person;
:hasCollectionIndirector [foaf:knows </gregg/knowsCollection>] .
This could then reference the same type of collection I described above. It sort of breaks foaf:knows, except it does so on a blank resource, which could have some catch-all semantic description, and it at least does not mess up the definition of the primary Person resource.
I see many advantages to the 2nd proposal, but would really like to see this more actively discussed.
On Monday, May 12, 2014 8:15 PM, Gregg Kellogg wrote:
This topic's been quiet for a while, but for me, resolving this is pretty much my top priority. At this point, I think there are two basic solutions:
1) Use a separate collection property, which has some semantic relationship to the base property, where the range is specifically a collection. For example:
</gregg> a foaf:Person; :knowsCollection </gregg/knowsCollection> . :knowsCollection :collectionPropertyFor foaf:knows .
Interesting.. so you would set the link from knowsCollection to knows and not vice-versa? What about asserting it on a, what we currently call, SupportedProperty?
Then the collection can reference each member and re-assert the relationship
</gregg/knowsCollection> a hydra:Collection; hydra:member </markus> . </gregg> foaf:knows </markus> .
2) In a separate email, @lanthaler described an alternate using an intermediate object, such as the following:
</gregg> a foaf:Person; :hasRelationshipIndirector [foaf:knows </gregg/knowsCollection>] .
This could then reference the same type of collection I described above. It sort of breaks foaf:knows, except it does so on a blank resource, which could have somecatch-all semantic description, and it at least does not mess up the definition of the primary Person resource.
I see many advantages to the 2nd proposal, but would really like to see this more actively discussed.
I would also like to hear more opinions on this. I think it has a number of advantages but, as Gregg points out, it is a bit weird from a semantical point of view.
There's also a third option which would be somewhat similar to what LDP does. Namely assert what subject-property pair the collection is managing. Something like
</gregg/knowsCollection> :manages [
:subject </gregg/> ;
:property foaf:knows
] .
The link to the collection can then be done by something very generic such as rdf:seeAlso.
Last but not least, for some vocabularies (most notably Schema.org) simply sticking to the current approach would work as well but introduces an undesired triple unless you remove it when you ingest the data
</GreggKellog> schema:knows </gregg/knowsCollection>
Gregg, at this stage, what would be your preferred approach?
Markus Lanthaler @markuslanthaler
On Monday, May 12, 2014 8:15 PM, Gregg Kellogg wrote: This topic's been quiet for a while, but for me, resolving this is pretty much my top priority. At this point, I think there are two basic solutions:
1) Use a separate collection property, which has some semantic relationship to the base property, where the range is specifically a collection. For example:
</gregg> a foaf:Person; :knowsCollection </gregg/knowsCollection> .
:knowsCollection :collectionPropertyFor foaf:knows .
Interesting.. so you would set the link from knowsCollection to knows and not vice-versa? What about asserting it on a, what we currently call, SupportedProperty?
I was just illustrating such a possible assertion. In fact, I did create a hydra:collectionProperty to use on a SupportedProperty, but I didn't find this particularly transparent or satisfying. In fact, it's easier to consider foaf:knows to not be a supported property, in this case.
Then the collection can reference each member and re-assert the relationship
</gregg/knowsCollection> a hydra:Collection;
hydra:member </markus> .
</gregg> foaf:knows </markus> .
2) In a separate email, @lanthaler described an alternate using an intermediate object, such as the following:
</gregg> a foaf:Person;
:hasRelationshipIndirector [foaf:knows </gregg/knowsCollection>] .
This could then reference the same type of collection I described above. It sort of breaks foaf:knows, except it does so on a blank resource, which could have some catch-all semantic description, and it at least does not mess up the definition of the primary Person resource.
I see many advantages to the 2nd proposal, but would really like to see this more actively discussed.
I would also like to hear more opinions on this. I think it has a number of advantages but, as Gregg points out, it is a bit weird from a semantical point of view.
There's also a third option which would be somewhat similar to what LDP does. Namely assert what subject-property pair the collection is managing. Something like
</gregg/knowsCollection> :manages [
:subject </gregg/> ;
:property foaf:knows
] .
This is also quite close to something Nikas suggested from the VOID vocabulary:
</gregg> a foaf:Person;
rdfs:seeAlso [
a void:Linkset;
void:subjectsTarget </gregg>;
void:objectsTarget </gregg/friends>;
void:linkPredicate foaf:knows
] .
Although, this does not assert the relationship in the Collection, but in the Linkset. It does have the advantage of being a pattern from a widley-deployed vocabulary for describing datasets.
The link to the collection can then be done by something very generic such as rdf:seeAlso.
In your example, the seeAlso would presumably directly reference the collection, but would need to extract some useful properties of that collection, perhaps like this:
</gregg> a foaf:Person;
rdfs:seeAlso </gregg/friends> .
</gregg/friends> a hydra:Collection;
:manages [
:property foaf:knows;
:subject </gregg>
] .
They really both have the same amount of indirection, but in your case, it's more :subject => :collection => :manages, and in the VOID case, its :subject => :Linkset => :collection, which does seem a little more natural to me.
Last but not least, for some vocabularies (most notably Schema.org) simply sticking to the current approach would work as well but introduces an undesired triple unless you remove it when you ingest the data
</GreggKellog> schema:knows </gregg/knowsCollection>
Well, I've already objected to this pattern, so that would be a no-go for me.
Gregg, at this stage, what would be your preferred approach?
Markus Lanthaler @markuslanthaler
Gregg
Any news on this issue? (I also think that it is an important one)
Markus documented the state of discussion on this Wiki page: https://www.w3.org/community/hydra/wiki/Avoid_that_collections_%22break%22_relationships
Call for consensus: http://lists.w3.org/Archives/Public/public-hydra/2014Jul/0010.html
+1
Proposed by Gregg: Make it a best practice that a Collection serialization include the hydra:manages block inline, rather than requiring an additional GET
:+1: for inlining the hydra:manages
block.
RESOLVED: Introduce four new properties, namely hydra:collection
, hydra:manages
, hydra:subject
, and hydra:object
, to describe collections and associate them to entities. Declare it a best practice to inline the "manages block" in collection representations.
This decision doesn't address issue #42 (paging) and still leaves it open how the "manages block" will be called; I've raised issue #60 for that.
Has this been implemented? Is there a (presumably unstable) spec that includes hydra:collection
, hydra:manages
, hydra:subject
and hydra:object
? If not, when will such a spec be published?
Jacopo, it has been decided that this is the design that Hydra will use. The spec, however, hasn’t been updated yet (that’s also the reason why this issues is still open).
Btw. you know that there’s a W3C Community Group working on Hydra (http://www.w3.org/community/hydra/), right? I’d like to invite you to join that group if you are interested in this work. The process to join the group is described in detail at http://www.hydra-cg.com/#community
On Mar 18, 2014, at 3:13 PM, Markus Lanthaler wrote:
Gregg also suggests to also include "some best practices for dealing with the potential confusion"