Create Variable in RDF model api

37 views
Skip to first unread message

Tim M

unread,
May 31, 2021, 5:11:15 PM5/31/21
to RDF4J Users
Hi

the rdf model api (https://rdf4j.org/documentation/programming/model/) allows to create IRIs, Literals and Statements, but how can I create a variable (like ?x)? I want to use variables in an insert sparql query. Is there another way to use variables in my queries?

Tim

Jeen Broekstra

unread,
May 31, 2021, 7:10:04 PM5/31/21
to RDF4J Users

On Tue, 1 Jun 2021, at 07:11, Tim M wrote:
Hi

the rdf model api (https://rdf4j.org/documentation/programming/model/) allows to create IRIs, Literals and Statements, but how can I create a variable (like ?x)? I want to use variables in an insert sparql query. Is there another way to use variables in my queries?

It depends on how you create your SPARQL queries.

If you are simply creating SPARQL queries as strings, then you don't need anything special to create variables, you just create the query string with the variable in it and then prepare it:

String queryString = "SELECT ?x WHERE { ?x a <http://example.org/Person> }";
TupleQuery query = conn.prepareTupleQuery(queryString);

If you are using the SparqlBuilder to create queries, then you can create variables using the SparqlBuilder.var method:

Variable x = SparqlBuilder.var("x");

That's all there is to it, really.

Jeen

Tim M

unread,
Jun 3, 2021, 4:09:15 PM6/3/21
to RDF4J Users
Thanks for your answer. Helped me alot.

I have a couple more questions.
1. How can I get the type (Literal, Variable, ...) from a Statement? I tried it like this, but I get a NoSuchElementException.
SPARQLParser parser = new SPARQLParser();
ParsedUpdate parsed = parser.parseUpdate(sparql, "http://example.org/");

Iterator<UpdateExpr> expr = parsed.getUpdateExprs().iterator();
UpdateExpr updateExpr = expr.next();

InsertData insertDataExpr = (InsertData) updateExpr;
RDFParser rdfParser = new SPARQLUpdateDataBlockParser();
StatementCollector handler = new StatementCollector();
parser.setRDFHandler(handler);

rdfParser .parse(new StringReader(insertDataExpr.getDataBlock()), "");
Iterator<Statement> iterator = handler.getStatements().iterator();

System.out.println("Subject: " + iterator.next().getSubject());

2. Can I build a query with a different triple format? Like predicate (subject, object) instead of subject, predicate, object.

Thanks in advance.
Tim

Jeen Broekstra

unread,
Jun 4, 2021, 2:42:47 AM6/4/21
to RDF4J Users


On Fri, 4 Jun 2021, at 06:09, Tim M wrote:
Thanks for your answer. Helped me alot.

I have a couple more questions.
1. How can I get the type (Literal, Variable, ...) from a Statement? I tried it like this, but I get a NoSuchElementException.
SPARQLParser parser = new SPARQLParser();
ParsedUpdate parsed = parser.parseUpdate(sparql, "http://example.org/");

Iterator<UpdateExpr> expr = parsed.getUpdateExprs().iterator();
UpdateExpr updateExpr = expr.next();

InsertData insertDataExpr = (InsertData) updateExpr;
RDFParser rdfParser = new SPARQLUpdateDataBlockParser();
StatementCollector handler = new StatementCollector();
parser.setRDFHandler(handler);

rdfParser .parse(new StringReader(insertDataExpr.getDataBlock()), "");
Iterator<Statement> iterator = handler.getStatements().iterator();

System.out.println("Subject: " + iterator.next().getSubject());

Can you give a bit of background on what you're trying to achieve here?  Why are you parsing and inspecting a SPARQL update query in this way? If the goal is to get the statements from a SPARQL update, a possibly simpler approach might be to just execute the update (on a MemoryStore, for example) and then query that store for the statements.

That said, I am not immediately spotting anything wrong in your code. A NoSuchElementException just means that the iterator is empty, which either means that your query's datablock was empty, or the data block parser somehow failed. You could try setting an error handler on it to see what is going wrong. 

2. Can I build a query with a different triple format? Like predicate (subject, object) instead of subject, predicate, object.

I don't understand the question. What do you mean with "build a query"? And what are you trying to achieve with this "different triple format"?

Jeen


Tim M

unread,
Jun 4, 2021, 4:06:08 PM6/4/21
to RDF4J Users
So,
1. I found the error and solved it. Thanks.
2. My goal is to parse a INSERT DATA/INSERT Sparql query and build a equivalent datalog rule out of it. I use a datalog framework that is only accepting the triple format predicate (subject, object). Hence, to convert the formats/syntaxes I need to get each query statement. With INSERT DATA queries it is pretty simple, but now I have a problem with the INSERT query. How can I iterate through a UpdateExpr (like the UpdateExpr used here https://stackoverflow.com/questions/55118469/how-get-updateexpr-when-i-execute-insert-query-rdf4j) and get each Statement in a StatementPattern? Can I do this without using a MemoryStore?

Thanks in advance

Tim

Jeen Broekstra

unread,
Jun 4, 2021, 9:03:24 PM6/4/21
to RDF4J Users


On Sat, 5 Jun 2021, at 06:06, Tim M wrote:
So,
1. I found the error and solved it. Thanks.

Good to hear.

2. My goal is to parse a INSERT DATA/INSERT Sparql query and build a equivalent datalog rule out of it. I use a datalog framework that is only accepting the triple format predicate (subject, object). Hence, to convert the formats/syntaxes I need to get each query statement. With INSERT DATA queries it is pretty simple, but now I have a problem with the INSERT query. How can I iterate through a UpdateExpr (like the UpdateExpr used here https://stackoverflow.com/questions/55118469/how-get-updateexpr-when-i-execute-insert-query-rdf4j) and get each Statement in a StatementPattern? Can I do this without using a MemoryStore?

Ah I see. I think you'll need to step back a little bit and consider the general approach. When you parse SPARQL query in RDF4J, the result (the TupleExpr or UpdateExpr) is an algebra representation of that query. It's a tree structure of algebra operators (StatementPatterns, Joins, Projections, Extensions, etc). 

To turn such a structure back into a serialized representation (like back to a SPARQL query string, or to a Datalog query), the best way to go about is implement a tree visitor (extend AbstractQueryModelVisitor). The idea is that you can then focus on each node in the tree individually and decide how you want it rendered. This, for example, is also how the SPARQL query renderer is implemented. I would advise to base your code on a similar approach - you can look at org.eclipse.rdf4j.queryrender.sparql.SPARQLQueryRenderer for some inspiration.

The update datablock that you've been working with sofar is an exception to all of this: RDF4J's SPARQL parser deliberately does not actually parse the data block in an INSERT DATA for scalability reasons. But everything else is transformed into algebra expressions. 

Jeen

Thanks in advance

Tim

Jeen Broekstra schrieb am Freitag, 4. Juni 2021 um 08:42:47 UTC+2:


On Fri, 4 Jun 2021, at 06:09, Tim M wrote:
Thanks for your answer. Helped me alot.

I have a couple more questions.
1. How can I get the type (Literal, Variable, ...) from a Statement? I tried it like this, but I get a NoSuchElementException.
SPARQLParser parser = new SPARQLParser();
ParsedUpdate parsed = parser.parseUpdate(sparql, "http://example.org/");

Iterator<UpdateExpr> expr = parsed.getUpdateExprs().iterator();
UpdateExpr updateExpr = expr.next();

InsertData insertDataExpr = (InsertData) updateExpr;
RDFParser rdfParser = new SPARQLUpdateDataBlockParser();
StatementCollector handler = new StatementCollector();
parser.setRDFHandler(handler);

rdfParser .parse(new StringReader(insertDataExpr.getDataBlock()), "");
Iterator<Statement> iterator = handler.getStatements().iterator();

System.out.println("Subject: " + iterator.next().getSubject());

Can you give a bit of background on what you're trying to achieve here?  Why are you parsing and inspecting a SPARQL update query in this way? If the goal is to get the statements from a SPARQL update, a possibly simpler approach might be to just execute the update (on a MemoryStore, for example) and then query that store for the statements.

That said, I am not immediately spotting anything wrong in your code. A NoSuchElementException just means that the iterator is empty, which either means that your query's datablock was empty, or the data block parser somehow failed. You could try setting an error handler on it to see what is going wrong. 

2. Can I build a query with a different triple format? Like predicate (subject, object) instead of subject, predicate, object.

I don't understand the question. What do you mean with "build a query"? And what are you trying to achieve with this "different triple format"?

Jeen



--
You received this message because you are subscribed to the Google Groups "RDF4J Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rdf4j-users...@googlegroups.com.

Reply all
Reply to author
Forward
0 new messages