How do i extract the fragment value, the bit after #, in a SPARQL query - sparql

I wrote the following jena query in Eclipse which produces a URI and description of a medical disorder pertaining to the inner ear.
public static void main(String[] args) {
String FOAF = "http://http://xmlns.com/foaf/0.1/";
String NS = "http://philshields.altervista.org/owl/_";
String rdf= "http://www.w3.org/1999/02/22-rdf-syntax-ns#";
String owl= "http://www.w3.org/2002/07/owl#" ;
String xsd= "http://www.w3.org/2001/XMLSchema#";
String rdfs= "http://www.w3.org/2000/01/rdf-schema#";
String dc= "http://purl.org/dc/elements/1.1/";
Model model = ModelFactory.createOntologyModel( OntModelSpec.OWL_MEM );
//model = FileManager.get().loadModel("c:/Ontologies/ICD-10 ontologies/2017_10_26_ICD10_AM_Code Order.owl");
model = FileManager.get().loadModel("c:/jena/ICD.owl");
String resultsAsString;
String queryString = "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>\r\n" +
"PREFIX owl: <http://www.w3.org/2002/07/owl#>\r\n" +
"PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>\r\n" +
"PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>\r\n" +
"PREFIX dc: <http://purl.org/dc/elements/1.1/>\r\n" +
"SELECT (str(?subject) AS ?string) ?object\r\n" +
" WHERE {?subject dc:title ?object \r\n" +
"FILTER regex(?object,\"inner ear\",\"i\")}\r\n" +
"" ;
Query query = QueryFactory.create(queryString) ;
try (QueryExecution qexec = QueryExecutionFactory.create(query, model)) {
ResultSet results = qexec.execSelect() ;
for ( ; results.hasNext() ; )
{
//QuerySolution soln = results.nextSolution() ;
ResultSetFormatter.out(System.out, results, query) ;
}
}
}
It produces the correct results shown here:
-------------------------------------------------------------------------------------------------------------------------------------
| string | object |
=====================================================================================================================================
| "http://www.semanticweb.org/philshields/ontologies/2017/8/untitled-ontology-341#H83.3" | "Noise effects on inner ear" |
| "http://www.semanticweb.org/philshields/ontologies/2017/8/untitled-ontology-341#S01.38" | "Open wound of inner ear" |
| "http://www.semanticweb.org/philshields/ontologies/2017/8/untitled-ontology-341#H83.8" | "Other specified diseases of inner ear" |
| "http://www.semanticweb.org/philshields/ontologies/2017/8/untitled-ontology-341#H83.9" | "Disease of inner ear, unspecified" |
I am trying to discard all of the URI and keep the fragment value which is the code number of the disorder after the hash.
I tried using SELECT (str(?subject) AS ?string) ?object, but it does not work.

SPARQL way:
SELECT (strafter(str(?subject), "#") as ?fragment) WHERE
{
#... Something...
}
JAVA way:
Resource subject = // Some way to fetch from your query;
String fragment = resource.getlocalName(); // This will return fragment

Related

Access subclassOf/subclassOf level using ForwardChainingRDFSInferencer with SPARQL

I am running some SPARQL queries using the class ForwardChainingRDFSInferencer, which basic constructs an inferencer. For my examples I use the schema.org ontology.
My code looks like the following example
MemoryStore store = new MemoryStore();
ForwardChainingRDFSInferencer inferencer = new ForwardChainingRDFSInferencer(store); //the inference class
Repository repo = new SailRepository(inferencer);
repo.initialize();
URL data = new URL("file:/home/user/Documents/schemaorg-current-https.nt");
RDFFormat fileRDFFormat = RDFFormat.NTRIPLES;
RepositoryConnection con = repo.getConnection();
con.add(data, null, fileRDFFormat);
System.out.println("Repository loaded");
String queryString =
" PREFIX schema: <https://schema.org/>" +
" SELECT DISTINCT ?subclassName_one" +
" WHERE { " +
" ?type rdf:type rdfs:Class ." +
" ?type rdfs:subClassOf/rdfs:subClassOf? schema:Thing ." +
" ?type rdfs:label ?subclassName_one ." +
" }";
TupleQuery tupleQuery = con.prepareTupleQuery(QueryLanguage.SPARQL, queryString);
TupleQueryResult result = tupleQuery.evaluate();
while (result.hasNext()) {
BindingSet bindingSet = result.next();
System.out.println(bindingSet.toString());
stdout.println(bindingSet.toString());
}
repo.close()
What I want is to print two subclass levels down the class Thing. So if for example we have,
Thing > Action (sub-class 1) > ConsumeAction (sub-class 2) > DrinkAction
What I want is to return the class CosumeAction which is two levels (subclasses) down from class Thing, while using the inference java class.
The current query, as given in the code sample above, returns all the classes and subclasses from every class of the schema.org ontology. Thus, there is something that I do wrong while using the inference class.
You could remove the classes you are not interested in with FILTER NOT EXISTS:
FILTER NOT EXISTS {
?type rdfs:subClassOf+/rdfs:subClassOf/rdfs:subClassOf schema:Thing .
}
Examples
For DrinkAction (level 3):
FILTER NOT EXISTS {
?type
rdfs:subClassOf+ / # schema:ConsumeAction
rdfs:subClassOf / # schema:Action
rdfs:subClassOf schema:Thing .
}
For WearAction (level 4):
FILTER NOT EXISTS {
?type
rdfs:subClassOf+ / # schema:UseAction / schema:ConsumeAction
rdfs:subClassOf / # schema:Action
rdfs:subClassOf schema:Thing .
}

How to convert a class expression (from restriction unionOf) to a string?

A SPARQL query returns a result with restrictions with allValuesFrom and unionOf. I need do concat these values, but, when I use bind or str functions, the result is blank.
I tried bind, str and group_concat functions, but, all of it was unsuccessful. Group_concat return a blank node.
SELECT DISTINCT ?source ?is_succeeded_by
WHERE {
?source rdfs:subClassOf ?restriction .
?restriction owl:onProperty j.0:isSucceededBy .
?restriction owl:allValuesFrom ?is_succeeded_by .
FILTER (REGEX(STR(?source), 'gatw-Invoice_match'))
}
Result of SPARQL query in Protegé:
You can hardly obtain strings like 'xxx or yyy' programmatically in Jena,
since it is Manchester Syntax, an OWL-API native format, and it is not supported by Jena.
Any class expression is actually b-node, there are no such builtin symbols like 'or' in raw RDF.
To represent any anonymous class expression as a string, you can use ONT-API,
which is a jena-based OWL-API, and, therefore, both SPARQL and Manchester Syntax are supported there.
Here is an example based on pizza ontology:
// use pizza, since no example data provided in the question:
IRI pizza = IRI.create("https://raw.githubusercontent.com/owlcs/ont-api/master/src/test/resources/ontapi/pizza.ttl");
// get OWLOntologyManager instance from ONT-API
OntologyManager manager = OntManagers.createONT();
// as extended Jena model:
OntModel model = manager.loadOntology(pizza).asGraphModel();
// prepare query that looks like the original, but for pizza
String txt = "SELECT DISTINCT ?source ?is_succeeded_by\n" +
"WHERE {\n" +
" ?source rdfs:subClassOf ?restriction . \n" +
" ?restriction owl:onProperty :hasTopping . \n" +
" ?restriction owl:allValuesFrom ?is_succeeded_by .\n" +
" FILTER (REGEX(STR(?source), 'Am'))\n" +
"}";
Query q = new Query();
q.setPrefixMapping(model);
q = QueryFactory.parse(q, txt, null, Syntax.defaultQuerySyntax);
// from owlapi-parsers package:
OWLObjectRenderer renderer = new ManchesterOWLSyntaxOWLObjectRendererImpl();
// from ont-api (although it is a part of internal API, it is public):
InternalObjectFactory iof = new SimpleObjectFactory(manager.getOWLDataFactory());
// exec SPARQL query:
try (QueryExecution exec = QueryExecutionFactory.create(q, model)) {
ResultSet res = exec.execSelect();
while (res.hasNext()) {
QuerySolution qs = res.next();
List<Resource> vars = Iter.asStream(qs.varNames()).map(qs::getResource).collect(Collectors.toList());
if (vars.size() != 2)
throw new IllegalStateException("For the specified query and valid OWL must not happen");
// Resource (Jena) -> OntCE (ONT-API) -> ONTObject (ONT-API) -> OWLClassExpression (OWL-API)
OWLClassExpression ex = iof.getClass(vars.get(1).inModel(model).as(OntClass.class)).getOWLObject();
// format: 'class local name' ||| 'superclass string in ManSyn'
System.out.println(vars.get(0).getLocalName() + " ||| " + renderer.render(ex));
}
}
The output:
American ||| MozzarellaTopping or PeperoniSausageTopping or TomatoTopping
AmericanHot ||| HotGreenPepperTopping or JalapenoPepperTopping or MozzarellaTopping or PeperoniSausageTopping or TomatoTopping
Used env: ont-api:2.0.0, owl-api:5.1.11, jena-arq:3.13.1

Does Jena TDB load all data into memory every time?

I am a newbie of Jena. I try to deal with the Yoga dataset using TDB. The dataset is about 200M and everytime I run the same query, it will have to take about 5 minutes to load the data then give out the results. I am wondering do I misunderstand any part of TDB? The following are my codes.
String directory = "tdb";
Dataset dataset = TDBFactory.createDataset(directory);
dataset.begin(ReadWrite.WRITE);
Model tdb = dataset.getDefaultModel();
//String source = "yagoMetaFacts.ttl";
//FileManager.get().readModel(tdb, source);
String queryString = "SELECT DISTINCT ?p WHERE { ?s ?p ?o. }";
Query query = QueryFactory.create(queryString);
try(QueryExecution qexec = QueryExecutionFactory.create(query, tdb)){
ResultSet results = qexec.execSelect();
ResultSetFormatter.out(System.out, results, query) ;
}
dataset.commit();
dataset.end();
There are two ways to load data into tdb, either by API or CMD. Much thanks to #ASKW and #AndyS
1 Load data via API
These codes need to be executed only once especially the readModel line which will takes long time.
String directory = "tdb";
Dataset dataset = TDBFactory.createDataset(directory);
dataset.begin(ReadWrite.WRITE);
Model tdb = dataset.getDefaultModel();
String source = "yagoMetaFacts.ttl";
FileManager.get().readModel(tdb, source);
dataset.commit(); //Important!! This is to commit the data to tdb.
dataset.end();
After the data is loaded into tdb, we can use following codes to query. And it is not necessary to load data again.
String directory = "path\\to\\tdb";
Dataset dataset = TDBFactory.createDataset(directory);
Model tdb = dataset.getDefaultModel();
String queryString = "SELECT DISTINCT ?p WHERE { ?s ?p ?o. }";
Query query = QueryFactory.create(queryString);
try(QueryExecution qexec = QueryExecutionFactory.create(query, tdb)){
ResultSet results = qexec.execSelect();
ResultSetFormatter.out(System.out, results, query) ;
}
2 Load data via CMD
To load data
>tdbloader --loc=path\to\tdb path\to\dataset.ttl
To query
>tdbquery --loc=path\to\tdb --query=q1.rq
q1.rq is the file which stores the query
Should get results like this
-------------------------------------------------------
| p |
=======================================================
| <http://yago-knowledge.org/resource/hasGloss> |
| <http://yago-knowledge.org/resource/occursSince> |
| <http://yago-knowledge.org/resource/occursUntil> |
| <http://yago-knowledge.org/resource/byTransport> |
| <http://yago-knowledge.org/resource/hasPredecessor> |
| <http://yago-knowledge.org/resource/hasSuccessor> |
| <http://www.w3.org/2000/01/rdf-schema#comment> |
-------------------------------------------------------

Simple Jena SPARQL query not working

What am I doing wrong here?
public class SimpleSearchTest {
public static void main(String[] args) throws Exception {
Model model = ModelFactory.createDefaultModel();
model.getGraph().add(new Triple(Node.createURI("a"), Node.createURI("b"), Node.createURI("c")));
String queryString = "SELECT ?p ?o WHERE { <a> ?p ?o }";
Query query = QueryFactory.create(queryString);
QueryExecution qExec = QueryExecutionFactory.create(query, model);
ResultSetFormatter.out(qExec.execSelect());
}
}
I am expecting
-------------
| p | o |
=============
| <b> | <c> |
-------------
But instead I am getting no results:
---------
| p | o |
=========
---------
I am sure it is something dumb...
I think the SPARQL parser isn't liking your <a> because it's not a legal URI (though it's odd that you don't get a warning). If you change your code as follows:
model.getGraph().add(new Triple(Node.createURI("http://example.com/a"), Node.createURI("b"), Node.createURI("c")));
String queryString = "SELECT ?p ?o WHERE { <http://example.com/a> ?p ?o }";
you get the result you are expecting.
Parenthetically, by creating the test graph with Node.createURI() you are using the lower-level internal Graph API, rather than the more normally used Model API. It's perfectly fine to do this, but the Graph API generally assumes you know more what you are doing, and may have fewer checks against doing the unexpected.

Sparql Query With Inferencing

i have some rdf & rdfs files and i want to use jena sparql implementation to query it and my code look like :
//model of my rdf file
Model model = ModelFactory.createMemModelMaker().createDefaultModel();
model.read(inputStream1, null);
//model of my ontology (word net) file
Model onto = ModelFactory.createOntologyModel( OntModelSpec.RDFS_MEM_RDFS_INF);
onto.read( inputStream2,null);
String queryString =
"PREFIX rdf:<http://www.w3.org/1999/02/22-rdf-syntax-ns#> "
+ "PREFIX wn:<http://www.webkb.org/theKB_terms.rdf/wn#> "
+ "SELECT ?person "
+ "WHERE {"
+ " ?person rdf:type wn:Person . "
+ " }";
Query query = QueryFactory.create(queryString);
QueryExecution qe = QueryExecutionFactory.create(query, ????);
ResultSet results = qe.execSelect();
ResultSetFormatter.out(System.out, results, query);
qe.close();
and i have a wordNet Ontology in rdf file and i want to use this ontology in my query to do Inferencing automaticly (when i query for person the query should return eg. Man ,Woman)
so how to link the ontology to my query? please help me.
update: now i have tow models : from which i should run my query ?
QueryExecution qe = QueryExecutionFactory.create(query, ????);
thanks in advance.
The key is to recognise that, in Jena, Model is the one of the central abstractions. An inferencing model is just a Model, in which some of the triples are present because they are entailed by inference rules rather than read in from the source document. Thus you only need to change the first line of your example, where you create the model initially.
While you can create inference models directly, it's often easiest just to create an OntModel with the required degree of inference support:
Model model = ModelFactory.createOntologyModel( OntModelSpec.RDFS_MEM_RDFS_INF );
If you want a different reasoner, or OWL support, you can select a different OntModelSpec constant. Be aware that large and/or complex models can make for slow queries.
Update (following edit of original question)
To reason over two models, you want the union. You can do this through OntModel's sub-model factility. I would change your example as follows (note: I haven't tested this code, but it should work):
String rdfFile = "... your RDF file location ...";
Model source = FileManager.get().loadModel( rdfFile );
String ontFile = "... your ontology file location ...";
Model ont = FileManager.get().loadModel( ontFile );
Model m = ModelFactory.createOntologyModel( OntModelSpec.RDFS_MEM_RDFS_INF, ont );
m.addSubModel( source );
String queryString =
"PREFIX rdf:<http://www.w3.org/1999/02/22-rdf-syntax-ns#> "
+ "PREFIX wn:<http://www.webkb.org/theKB_terms.rdf/wn#> "
+ "SELECT ?person "
+ "WHERE {"
+ " ?person rdf:type wn:Person . "
+ " }";
Query query = QueryFactory.create(queryString);
QueryExecution qe = QueryExecutionFactory.create(query, m);
ResultSet results = qe.execSelect();
ResultSetFormatter.out(System.out, results, query);
qe.close();