How to add triples to a jena Query - java

Suppose I have some jena query object :
String query = "SELECT * WHERE{ ?s <some_uri> ?o ...etc. }";
Query q = QueryFactory.create(query, Syntax.syntaxARQ);
How would one go about getting information about the jena query object and adding in triples to it iteratively in an effective manner? For example, suppose I wanted to add in the triples
?o dcterms:title "TheBestTitle".
?o dcterms:date ?date.
to the query, and perhaps more.
Is there some way to add in these triples to the query, or do some magic to create a new query object which looks like the original with those triples added in? Assume that I may need to grab information from the original version of the query as well (for example, List resultVars = q.getResultVars();).
Some leads I have are to use the AlgebraGenerator and Op Classes provided by the Jena API, but I can't seem to find any reasonable use cases in a context such as this.
Thanks!

http://jena.apache.org/documentation/query/manipulating_sparql_using_arq.html
Construct an algebra expression and convert to a query (OpAsQuery)
The Query object, which is the cleaned up parsed struture, can be manipulated (Query.getQueryPattern)
Do it by string manipulation before parsing.

Related

How to query multi-valued array fields in Elasticsearch using Java client?

Using the Elasticsearch High Level REST Client for Java v7.3
I have a few fields in the schema that look like this:
{
"document_type" : ["Utility", "Credit"]
}
Basically one field could have an array of strings as the value. I not only need to query for a specific document_type, but also a general string query.
I've tried the following code:
QueryBuilder query = QueryBuilders.boolQuery()
.must(QueryBuilders.queryStringQuery(terms))
.filter(QueryBuilders.termQuery("document_type", "Utility"));
...which does not return any results. If I remove the ".filter()" part the query returns fine, but the filter appears to prevent any results from coming back. I'm suspecting it's because document_type is a multi-valued array - maybe I'm wrong though. How would I build a query query all documents for specific terms, but also filter by document_type?
I think, the reason is the wrong query. Consider using the terms query instead of term query. There is also a eqivalent in the java api.
Here is a good overview of the query qsl queries and their eqivalent in the high level rest client: https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/java-rest-high-query-builders.html

How to get all properties from a URI (jena, RDF, dbpedia)?

Suppose the URI is http://dbpedia.org/page/Ansungtangmyun from the Named Graph http://dbpedia.org, within Data Space dbpedia.org
This resource includes the following properties:
dbo:abstract
dbo:wikipageid
dct:subject
rdfs:comment
etc.
What I have tried is to get one property at a time by exploring the graph. I am using Jena. To enhance the performance, I would like to ask whether there is a way/API to get all properties at once?
First thing, I'd use the resource ID URI --
http://dbpedia.org/resource/Ansungtangmyun
-- instead of the HTML page URI --
http://dbpedia.org/page/Ansungtangmyun
-- which is to say, this query (and its live results) --
SELECT ?p ?o
WHERE
{
<http://dbpedia.org/resource/Ansungtangmyun> ?p ?o
}
You might also be interested in this (and its live results) --
DESCRIBE <http://dbpedia.org/resource/Ansungtangmyun>
Try the following SPARQL query:
SELECT ?p
WHERE {
<http://dbpedia.org/page/Ansungtangmyun> ?p ?o
}
You can directly get a whole graph having your property as subject by using a simple DESCRIBE query.
DESCRIBE <http://dbpedia.org/resource/Ansungtangmyun>

How to convert a hive string query into abstract syntax tree using Java API?

I know I can get the AST using the explain extended command. My question is, how to get the same using the Java API.
My goal is to get the following data about queries:
Database source and target (if applied).
Table source and target (if applied).
Fields involved in the query.
I know I can get them above data directly from query string using Regex, but I want to use Java API.
Do you have any other idea how to do that?
You can use Hive Parser for this. It simply takes the query and convert it into AST which is similar explain command. Here is a simple example:
ParseDriver pd = new ParseDriver();
ASTNode tree = pd.parse("Select * from table1");
System.out.println(tree.dump());
The output for this will be
nil
TOK_QUERY
TOK_FROM
TOK_TABREF
TOK_TABNAME
table1
TOK_INSERT
TOK_DESTINATION
TOK_DIR
TOK_TMP_FILE
TOK_SELECT
TOK_SELEXPR
TOK_ALLCOLREF
<EOF>

Parameterized SPARQL query with JENA

I'm trying to build a small semantic web application using Jena framework, JSP and JAVA. I have a remote SPARQL endpoint and I've already written a simple query which works fine but now I need to use some parameters. Here is my code so far:
final static String serviceEndpoint = "http://fishdelish.cs.man.ac.uk/sparql/";
String comNameQuery =
"PREFIX fd: <http://fishdelish.cs.man.ac.uk/rdf/vocab/resource/> " +
"SELECT ?name ?language ?type" +
"WHERE { ?nameID fd:comnames_ComName ?name ;" +
"fd:comnames_Language ?language ;" +
"fd:comnames_NameType ?type ." +
"}";
Query query = QueryFactory.create(comNameQuery);
QueryExecution qe = QueryExecutionFactory.sparqlService(serviceEndpoint,query);
try {
ResultSet rs = qe.execSelect();
if ( rs.hasNext() ) {
System.out.println(ResultSetFormatter.asText(rs));
}
}
catch(Exception e) {
System.out.println(e.getMessage());
}
finally {
qe.close();
}
What I want to do is to parameterized ?name. I'm new to Jena and I'm not really sure how to use parameters in a SPARQL query. I would appreciate it if someone could help me with this.
If you just want to restrict a variable to have a certain value for local queries you can do so with an overload of the QueryFactory.create() method which takes a QuerySolutionMap to set value restrictions. Note this doesn't alter your query just restricts the final results so this is not really parameterization.
If you want to actually have true parameterized queries (i.e. substitute variables for constants) then there are a couple of ways to do this depending on your version of ARQ.
Using any current release (up to 2.9.0) the only way to do it is string concatenation i.e. instead of having ?name in your query you would just insert the value you want e.g. "Bob"
Using the latest trunk (2.9.1-SNAPSHOT onwards) there is a new ParameterizedSparqlString class which makes this much more user friendly e.g.
ParameterizedSparqlString queryStr = new ParameterizedSparqlString(comNameQuery);
queryStr.setLiteral("name", "Bob");
Query query = QueryFactory.create(queryStr.toString());
And in fact you can simplify your code further since ParameterizedSparqlString has a StringBuffer style interface and can be used to build your query bit by bit and includes useful functionality like prepending prefixes to your query.
The advantage of this new method is that it provides a more generic way of doing parameterized queries that can also be used with updates and is usable for preparing remote queries which the existing methods do not cover.
You could try looking into Twinkql. It is a SPARQL-to-Java mapping framework. It uses Jena in the back end, but tries to simplify SPARQL queries and Java binding of the results.
It allows you to define SPARQL queries in xml:
<select id="getNovel" resultMap="novelResultMap">
<![CDATA[
SELECT ?novel ?author
WHERE {
?novel a <http://dbpedia.org/class/yago/EnglishNovels> ;
<http://dbpedia.org/property/name> "#{novelName}"#en ;
<http://dbpedia.org/property/author> ?author .
}
]]>
</select>
Note the #{novelName} placeholder -- this is where parameters can be passed in at query time.
Also, results can be bound to Java Beans:
<resultMap id="novelResultMap" resultClass="org.twinkql.example.Novel">
<uniqueResult>novel</uniqueResult>
<rowMap var="novel" varType="localName" beanProperty="name" />
<rowMap var="author" varType="localName" beanProperty="author"/>
</resultMap>
There is an API to call these queries, to pass in parameters, etc. It is much like MyBatis, but for SPARQL instead of SQL.

How to build SPARQL queries in java?

Is there a library, which is able to build SPARQL queries programmatically like the CriteriaBuilder in JPA or to build the queries like with a PreparedStatement for SQL?
Similar (for SQL): Cleanest way to build an SQL string in Java
You can build queries programmatically in Jena using two methods: syntax or algebra. There's an introduction in the jena wiki.
Using the algebra you'd do something like:
Op op;
BasicPattern pat = new BasicPattern(); // Make a pattern
pat.add(pattern); // Add our pattern match
op = new OpBGP(pat); // Make a BGP from this pattern
op = OpFilter.filter(e, op); // Filter that pattern with our expression
op = new OpProject(op, Arrays.asList(Var.alloc("s"))); // Reduce to just ?s
Query q = OpAsQuery.asQuery(op); // Convert to a query
q.setQuerySelectType(); // Make is a select query
(taken from the wiki page)
It's not CriteriaBuilder (nor was it intended to be), but is some of the way there. You OpJoin rather than AND, OpUnion when you want to OR, etc. The pain points are expressions in my experience: you probably want to parse them from a string.
The recent versions of Jena have added a StringBuilder style API for building query/update strings and parameterizing them if desired.
This class is called ParameterizedSparqlString, here's an example of using it to create a query:
ParameterizedSparqlString queryStr = new ParameterizedSparqlString();
queryStr.setNSPrefix("sw", "http://skunkworks.example.com/redacted#");
queryStr.append("SELECT ?a ?b ?c ?d");
queryStr.append("{");
queryStr.append(" ?rawHit sw:key");
queryStr.appendNode(someKey);
queryStr.append(".");
queryStr.append(" ?rawHit sw:a ?a .");
queryStr.append(" ?rawHit sw:b ?b .");
queryStr.append(" ?rawHit sw:c ?c . ");
queryStr.append(" ?rawHit sw:d ?d .");
queryStr.append("} ORDER BY DESC(d)");
Query q = queryStr.asQuery();
Disclaimer - I'm the developer who contributed this functionality to Jena
See What's the best way to parametize SPARQL queries? for more discussion on doing this across various APIs.
I implemented SPARQL Java - a kind of DSL for writing SPARQL queries in Java.
It solves the problem with IDE's auto formatting of concatenated SPARQL query strings and things like that.
As for example:
String shortQuery = Q.prefix("books", "http://example.org/books#")
.select("?book ?authorName", new where() {
{
$("?book books:author ?author");
$("?author books:authorName ?authorName");
}
}).get();
I recently started to use Sesame query builder. It looks promising except it doesn't provide much documentation and I struggled to find examples. Here is simple sample which may help you to get started:
ParsedTupleQuery query = QueryBuilderFactory
.select("pubProperty", "pubPropertyValue")
.group()
.atom(cmResource(resourceId), LinkPublicationsTransformation.REFERENCE_URI, "pubUri")
.atom("pubUri", "pubProperty", "pubPropertyValue")
.filter(isLiteral("pubPropertyValue"))
.closeGroup()
.query();
Just note that isLiteral and cmResource are my own little static helper classes. isLiteral stands for new IsLiteral(new Var("...")) for example where the latter one create URI with my heavily used prefix.
You might be then also interested in SPARQLQueryRenderer which can turn ParsedQuery into String which may be convenient for further usage.
If you end up using String(Builder) approach what I discourage you to do have at least a look on RenderUtils from sesame-queryrendered which has all the convenient methods to add < > around URIs, escape special characters etc.
The Eclipse RDF4J framework (the successor of Sesame) offers a Repository API which is somewhat similar to JDBC - it allows you to create a prepared Query object and inject variable bindings before executing it:
String query = "SELECT * WHERE {?X ?P ?Y }";
TupleQuery preparedQuery = conn.prepareQuery(QuerLanguage.SPARQL, query);
preparedQuery.setBinding("X", someValue);
...
TupleQueryResult result = preparedQuery.evaluate();
In addition, RDF4J has a SparqlBuilder (originally known as spanqit) - a Java DSL for SPARQL which allows you to create SPARQL queries in code like this:
query.prefix(foaf).select(name)
.where(x.has(foaf.iri("name"), name))
.orderBy(name)
.limit(5)
.offset(10);
I have just released a beta project to do just this, called Spanqit.
I strove for readability and an intuitive interface, for example, here is some example Spanqit syntax for creating a query:
query.prefix(foaf).select(name)
.where(x.has(foaf.iri("name"), name))
.orderBy(name)
.limit(5)
.offset(10);
Check it out, and feel free to comment and suggest improvements!
Jena provides a QueryBuilder in the Extras package.
https://jena.apache.org/documentation/extras/querybuilder/index.html
It does what you want.
You can use the Jena Semantic Framework (SPARQL documentation). Also take a look at this related question. Sadly, its syntax is closer to a SQL PreparedStatement than to the JPA.

Categories