How should embedded entities be declared in the Type Index Registry?


#1

I am developing an application that creates embedded entities, and I’m unsure how to declare these in the type index registry.

Maybe “embedded” is not the correct nomenclature for this, please correct me if there is a specific term. What I mean with embedded entities is the following. Imagine that I have this document in my POD at https://pod.example.com/movies/spirited-away:

@prefix : <#>.
@prefix movies: <./>.
@prefix ldp: <http://www.w3.org/ns/ldp#>.
@prefix schema: <https://schema.org/>.

movies:spirited-away
    a ldp:Resource, schema:Movie;
    schema:name "Spirited Away".
:abc
    a schema:WatchAction;
    schema:object movies:spirited-away.

In this case, the main entity of the document is the Spirited Away movie. But the document also contains an embedded schema:WatchAction related to this movie. I understand the proper way of declaring that movies can be found in /movies/ is this:

<#movies> a solid:TypeRegistration;
    solid:forClass schema:Movie;
    solid:instanceContainer </movies/>.

But how would I declare where schema:WatchAction can be found? The obvious thing that comes to mind is this:

<#actions> a solid:TypeRegistration;
    solid:forClass schema:WatchAction;
    solid:instanceContainer </movies/>.

But this isn’t correct. Semantically speaking, the /movies/ container only contains the movies. This also wouldn’t be a problem if I could reference the actions from the movie, but the only way to reference each other is using the schema:object property in the schema:WatchAction entity. I’ve found a way to declare reverse properties in JSON-LD, but I’m not sure if that can be done in turtle as well.

With all this knowledge, my conclusion is that the only proper way of doing this is not embedding entities. But then it makes my life a lot more difficult to find the actions for a given movie.

To clarify, this is not a problem in my application. I can assume that movie documents have embedded actions. But I wonder the proper way to declare this so that other applications can interact with the same data.

Any ideas?


#2

I’ve never done this and you probably need an opinion from an expert, but…

Maybe you could define a property, say watchedBy, on a schema:Movie with owl:inverseOf to use it as the inverse of WatchAction:object, like:

joe a Person.
spiritedAway a schema:Movie.
joeWatchesSpiritedAway a schema:WatchAction;
agent joe;
object spiritedAway.
spiritedAway:watchedBy a owl:ObjectProperty;
owl:inverseOf joeWatchesSpiritedAway:object.


#3

So if I my poor english-french translation understand your question, you’d like to know how to reference the WatchAction in all of your movie.ttl files?
Something like a wilcard ?

https://spoggy-test2.solid.community/public/movies/*.ttl#abc

Don’t know if it’s possible, but why not create a actions.ttl where you link to the movie folder?


#4

Maybe that works, let’s see if someone can confirm it.

My worries seeing this is if an application would know to look for it… My app for example is using the standard schema vocab, and I’m fairly confident that it’d work with pre-existing data using the same vocab if it’s declared in the type index. But given that this is not standard and is not documented on schema.org, I’m not sure how many applications would look for that property. Or go as far as “analyze” what the properties they don’t know mean.

On the other hand, using one document per entity and declaring both in the type index makes more sense and seems more standard. But matching movies with actions becomes a nightmare.


#5

I was not talking about a wildcard, I don’t think that’s correct because I could have different types of entities in a container.

As far as I understand, there are two ways of declaring things in the type registry: declaring what types of entities a Container contains and declaring individual type instances. I could use the second one (I forgot to mention that in my post), but that’d mean having a huge type index.

Other than the type index, I don’t know how an application would find the actions looking at the documentation in schema.org. The only documented property linking the classes references a movie from an action, but I want to infer actions from movies because that’ll be the main entity my application will browse (for example, if I do pagination could load the 10 first movies and I’d like to get all the actions for those movies).


#6

I don’t know, but it may be schema.org deliberately avoided making it easy to find who watched a movie or read a book. If thats the case then applications will have to find that in non standard ways. At least with inverseOf (if it works that way) you can get the inverseOf WatchAction:object without knowing what you named the inverse property (i.e. watchedBy).


#7

I think that is true if your concern is to be semantically correct. Then you have to split it up, as you mentioned, and store the watch actions in ../watch-action/spirited-away.ttl.

The typed index would then list a correct type registration, where the instances matche the defined class.

<#actions> a solid:TypeRegistration;
    solid:forClass schema:WatchAction;
    solid:instanceContainer </watch-action/>.

In that case, getting the watch action for a given movie includes two steps. First, filter all type registrations referencing watch actions and secondly find the instance that the action applies to.

But since it seems to me that it’s okay for you to define the action in the movie document (I would call it to define instead of to embed, but I am not sure too :grinning:, probably both are fine). Further, your goal is to make the watch action available to other application. Therefore the instance could point to the action /movies/spirited-away.ttl#abc in the type registration.

<#watch-action-spirited-away> a solid:TypeRegistration;
    solid:forClass schema:WatchAction;
    solid:instance </movies/spirited-away.ttl#abc>.

#8

I looked a little more into what might be a typical way to use schema:Movie.

It has a subjectOf property inherited from Thing, which is described as “A CreativeWork or Event about this Thing.”

So I think the correct way to do it would be to create a ScreeningEvent and make it a subjectOf the Movie. A ScreeningEvent has a property called attendee. That could be a foaf:Person. So that way you could get from the Movie back to who saw it.


#9

I am acutally seeing some confusion regarding nomenclature here, so let’s clear some things.

Why that? An RDF document contains a set of triples. There is no such thing as a main entity. Therefore there is also no “embedded” entity. The schema:Movie and the schema:WatchAction are no different in your document:

<https://pod.example.com/movies/spirited-away> a schema:Movie .
<https://pod.example.com/movies/spirited-away.ttl#abc> a schema:WatchAction .

That beeing said, what is wrong with

<#actions> a solid:TypeRegistration;
    solid:forClass schema:WatchAction;
    solid:instanceContainer </movies/>.

?

schema:WatchActions are being found in that container, so the type registration does not lie.


#10

Yeah, I’m not sure about the correct nomenclature for this. What I meant with “main entity” is the one matching the document url.

Reading your comment I noticed I had something wrong in my example. The filename is spirited-away.ttl but the url used to access it is https://pod.example.com/movies/spirited-away (without the trailing .ttl). I’ll edit my initial post to reflect that.

When I say it “lies” I mean that semantically it doesn’t contain the actions, only the movies. When I perfrom a GET /movies/ I get the following response:

@prefix movies: <>.
@prefix ldp: <http://www.w3.org/ns/ldp#>.
@prefix terms: <http://purl.org/dc/terms/>.
@prefix XML: <http://www.w3.org/2001/XMLSchema#>.
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>.
@prefix posix: <http://www.w3.org/ns/posix/stat#>.
@prefix turtle: <http://www.w3.org/ns/iana/media-types/text/turtle#>.

movies:
    a ldp:BasicContainer, ldp:Container, ldp:Resource;
    terms:created "2020-03-08T14:33:09Z"^^XML:dateTime;
    terms:modified "2020-03-08T14:33:09Z"^^XML:dateTime;
    rdfs:label "Movies";
    ldp:contains movies:spirited-away;
    posix:mtime 1589109600.587;
    posix:size 69632.

movies:spirited-away
    a turtle:Resource, ldp:Resource;
    terms:modified "2020-04-13T13:53:30Z"^^XML:dateTime;
    posix:mtime 1586786010.248;
    posix:size 673.

The actions are not listed as being part of the container, so there’s not way for me to know about their existence.


#11

I guess that’s a contrived way to work around it, but I’d rather use WatchAction because it seems more appropriate.


#12

Yes I also think this is correct, but I’d end up listing all the individual actions and that’s something I’d like to avoid.


#13

But if you want to distinguish between watching the same movie on an airplane, or in a big theater, or with family at home, and who was there, it would be useful. But anyway probably your main point was about how the type registry should work.

For that I think it should somehow be a function of what’s important to you.

If who you watch movies with is more important than the video format, then that should be reflected in the type registry. But that kind of thing isn’t the same for everyone. So how to customize the type registry…


#14

The document URL identifies, as the name implies, the document. Now there are two things mixed up. The document is not a movie. Usually a fragment like #it is appended to the document URL to identify a related non-information resource, but this is just a convention and implies nothing about “main” or “embedded” resources.

So, coming back to the type registration: this is just a way to point clients to documents where they can find resources of specific types, either to the documents directly or to a container containing those documents.


#15

But its obvious from the Movie example that there will be many ways different subtypes and related types that can be connected, either through the type registry or directly. That wiring will be important, especially for the first apps a pod owner uses related to a given subject. I don’t think how that’s done should be left entirely up to apps. It should be the result of some kind of negotiation between apps and the pod owner. Just sayin’…


#16

That’s something where shapes may be of help. The type index is only a way to find some resources to start with, but not how to continue from there


#17

But isn’t that like saying Google is only a way to find some resources to start with? :slight_smile:


#18

I think that misses the point of a typed index. The type implies that the instance follows some schema. Otherwise, you are left with a starting point that follows no specification. How to continue? The consequence would be that after some time, it probably ends up very messy.

I like to think of solid:instance and solid:forClass the same as in a typed language with a class and instance.


#19

No it does not, we are operating on an open-world assumption

I don’t think this analogy applies, typed languages have a closed-world schema.

But perhaps it makes sence to enhance the type index to support Shapes, so that you can find documents where not only specific types can be found, but also where to find data that is in a specific Shape I need. But this is nothing that is specified currently as far as I know. (On the other hand the whole type index stuff is just a proposal and not part of the spec :thinking:)


#20

Where does the spec proposal say that the typed index operates on an open-world assumption? I am ok with operating on an open-world assumption in general, but in that particular case of a typed index the spec should enforce a closed-world assumption.