How to leverage rdfs:subClassOf in the TO clause of SMS2

I would like my SMS2 mapping to be concise. The JSON (from mongodb) documents to be expressed in virtual graph have nearly identical structure - 80% made out of the same keys. However the rest of 20% is different.

For example imagine a movie database that has Documentary, Drama, Comedy, etc. All these would have 80% the same keys but in some cases Documentary will have a few other keys than Comedy or Drama.

  • So my challenge - how do I express this in the TO clause?

Right now i don't think rdfs:subClassOf is supported, right?

Thanks,
Radu

Hi Radu,
Are these different collections?

Nope - all documents are in the same mongodbcollection

Hi Radu,

If all the documents are in the same collection, you should be able to do this with one mapping. Let's say you have a boolean field isEnvironmentalDocumentary which is only present in documents representing Documentary films. If you include this in your mapping, queries using it will only return documentary films. Queries omitting it will return documents where it may not be present.

Jess,

Query time is important for my knowledge graph but so is visualization by specific class type.

My main SMS2 challenge is for each JSON document in collection to produce triple(s) that:

  1. Generate during query time specific (i.e. Documentary) instances that are of Movie super class.
  2. Generate during query time corresponding attributes and relationships (such as Episode partOfSeries)

Bullet one is key - it will allow business stakeholders to visually distinguish one type from another - very important! My visualization is configurable out of the box for specific rdf types (i.e. Classes).

My main pain with SMS2:

  • Currently there is no if / else SMS2 operator to generate either a Documentary or Drama rdf type that are subclasses of Movie rdf type.

Please concur that this is currently not possible or hopefully there is a workaround....

Thanks,
Radu

not sure I completely understood your question, however if you want to implicitely set type to drama or documentory if your datasource is a relational database, you can use a case statement to create this Label and then you simply

rdf:type: ?label

I use this approach in a few of my projects.

Radu,

I'm also having a tough time understanding your requirements here. Can you provide a simple example of what an IF/ELSE would look like and how you would use it? Perhaps we can use this to close the communication gap and allow us to help you find a solution.

Jess

Serge,

Thanks for trying to help. However my data resides in mongodb as json documents in in a mongodb collection. I believe you are refering to the manual - sql usage of case statement:

MAPPING <urn:employees>
FROM SQL {
  SELECT \"empno\", \"ename\", \"deptno\", (CASE \"job\"
    WHEN 'CLERK' THEN 'general-office'
    WHEN 'NIGHTGUARD' THEN 'security'
    WHEN 'ENGINEER' THEN 'engineering'
  END) AS ROLE FROM \"EMP\"
}

How can the same be accomplished against mongodb? My current mapping looks like:

MAPPING <urn:movies>
FROM GraphQL { 

I don't believe GraphQL allows for a case statement, does it? Can we provide a mongodb query? But that is not supported in Stardog yet, right?

Regards,
Radu

Jess,

Here are a couple JSON documents in a collection:

[
  {
    "movie-type":"Drama",
    "movie-name":"rama-drama",
    "fiction-rate": 0.6
  },
  {
    "movie-type":"Documentary",
    "movie-name":"doc-doc-doc",
    "realism-rate": 0.9
  }
]

So the goal is to produce a mapping that generates triples during query time for Drama and Documentary types that are subclasses of Movie class.
Movie class has only two attributes - "movie-type" and "movie-name".

Hope that helps,
Radu

Unless I miss anything you can simply use one of these method

#Method 1

?movieId a ?movieTypeId

And you make sure that you load the a rule for each

?movieTypeId rdfs:subClassOf <http//:.../Movie>

#Method 2
or you can use @jess suggestion where you don't set the type direction but rather infer it from movie-type property

After some thought, is your question regarding how you can use object inheritance? If yes, this is not object oriented programming and does not really work that way.

Neither @serge nor @jess are getting the point :frowning: - it is all about visualizing by rdf type.

It maybe very well be that I am not expressing the need clearly. Here we go again:

  • Based on two JSON documents above I need to create a virtual graph so that default select * SPARQL query would return two rdf types - :Documentary and and :Drama

  • Is it possible to create such a mapping today?

Thanks for trying to help,
Radu

Radu, can you provide the entirety of the select * SPARQL query you want to execute and your desired results?

If you could also provide the mappings you have tested, the results they generated given the same select * query, and how those are wrong then we should be able to get on the same page.

Here is the select:

select * { graph ?g { ?s ?p ?o } }

And I don't have a mapping - that is what I am trying to create - my intial thought was to use SMS2 GraphQL.

Regards,
Radu

Thanks.

Do you want results that look like this?

?s: <movie-id1>
?p: rdf:type
?o: :Drama

?s: <movie-id1>
?p: :friction-rate
?o: 0.6

and

?s: <movie-id2>
?p: rdf:type
?o: :Documentary

?s: <movie-id2>
?p: :realism-rate
?o: 0.9

I'm confused by this statement:

my intial thought was to use SMS2 GraphQL.

Do you mean you wish to use the SMS2 mappings to query your Mongo data from Stardog? I'm not sure what role GraphQL plays here.

Brian,

Yes - that is what I need the sparql query to return.

Yes - I want to query mongodb data - with whatever mapping you would recommend.

Thank you for your help,
Radu

Great. It looks like you are on the right track here -- my understanding is your use-case is supported and you do want to create an SMS mapping to translate your data in Mongo to triples query-able from Stardog.

I think one thing that may be confusing with how mappings work is if there is any part of your mapping file which does not apply to a particular Mongo document then it is simply ignored. For instance, if a mapping has ?movie :fictionRate ?fictionRate and a JSON document in Mongo doesn't have the ?fictionRate property then no triple will be returned with the predicate :fictionRate with that ?movie as the subject.

Below I sketched what you may want your mapping to look like (beware, I haven't tested so there may be syntax errors, missing namespace prefix declarations, etc).

The mapping can be roughly translated as:

"For each document in <mongo-collection-name>, first associate each attribute I wish to expose to Stardog to a variable in the FROM clause, then construct a URI to identify the document in the WHERE clause, and finally populate as much of the template in the TO clause as possible given the contents of this particular document -- in this example creating up to 4 triples from that document."

MAPPING FROM JSON {
  "<mongo-collection-name>": {
    "movie-type": ?movieTypeStr,
    "movie-name": ?movieNameStr,
    "fiction-rate": ?fictionRate,
    "realism-rate": ?realismRate,
  }
}
TO {
   ?movie rdf:type ?movieTypeCls ;
     rdfs:label ?movieNameStr ;
     :fictionRate ?fictionRate ;
     :realismRate ?realismRate .
}
WHERE {
    # TODO replace `http://foo.com` with a value appropriate to your setup
    BIND (template("http://foo.com/{movieTypeStr}") AS ?movieTypeCls)
}

Please test and iterate based on this, and then let us know how it goes!

Here's a link to the SMS2 docs:
https://www.stardog.com/docs/#_stardog_mapping_syntax_2

P.S. I see MAPPING FROM graphql is used as an example in this blog post, https://www.stardog.com/blog/native-mongodb-support-is-here/ . I haven't used that before, and the naming probably threw me off because it made me think of VGs consuming GraphQL APIs, but it should work just as well as the FROM JSON clause I provided as a method of associating the structure of JSON documents in your Mongo database to variables for use elsewhere in the mapping.

Brandon,

Unfortunately the above mapping will not work. Here is why:

The virtual graph created by your mapping will never return any :Drama or :Documentary triples. Only :Movie is going to be returned :frowning:

Why do you think that will not work?

When you say the mapping will never return :Drama or :Documentary triples, are you referring to triples that look like <movie-uri> rdf:type :Documentary?

Have you tested this? If so, please share an example of the incorrect query results.

Yes - there will be NO

in the sparql query result

This part of the mapping should generate URIs for the classes you desire.

While this part should use them to generate the triples you want in your results.

Given the example mappings I provided, where would :Movie come from?