Search code examples
sparqlrdf4j

How to construct long queries using rdf4j


I am trying to construct a long query using the rdf4j library and would like to use the count function that is available with SPARQL.

The original SPARQL query looks like this:

SELECT (COUNT(?letter) AS ?count) WHERE { \
    ?letter a :Letter . \
    ?letter :writtenBy :John . \
    ?letter :writtenOn ?date . \
    FILTER(?date > NOW() && }     

This is what I have so far using the rdf4j library

GraphPattern longPattern = GraphPatterns.tp(letter, ex.iri("a"), ex.iri("Letter")).
                and(GraphPatterns.tp(letter, ex.iri("writtenBy"), ex.iri("John"))).
                and(GraphPatterns.tp(letter, ex.iri("writtenOn"), date));

How can I implement the Count and use the NOW() functionality of sparql? I know there is a filter method but I don't know how to use the NOW() with it. All of the variables (letter, date) and a select query have been initialised within java using SparqlBuilder.


Solution

  • In the RDF4J SparqlBuilder, functions are created using org.eclipse.rdf4j.sparqlbuilder.constraint.Expressions static methods. For example, to create the BNode() function, you just do this:

    Expression bnodeFunc = Expressions.bnode();
    

    Similarly, for the COUNT aggregate function:

    Expression countAgg = Expressions.count(letter);
    

    and to use that in your SELECT clause, you'd do something like this:

    Variable count = SparqlBuilder.var("count");
    Projection select = SparqlBuilder.select(countAgg.as(count));
    

    As for the now() function: Annoyingly, the list of function factory methods in Expressions is incomplete: for now() there is no direct static factory method. However, you can use the general Expressions.function method to create it, as follows:

    Expression nowFunc = Expressions.function(SparqlFunction.NOW);
    

    By the way, your current graph pattern can be simplified quite a bit. Instead of this:

    GraphPattern longPattern = GraphPatterns.tp(letter, default.iri("a"), default.iri("Letter")).
                    and(GraphPatterns.tp(letter, default.iri("writtenBy"), legislate.iri("John"))).
                    and(GraphPatterns.tp(letter, legislate.iri("writtenOn"), date));
    

    Do this:

    TriplePattern longPattern = letter.isA(ex.iri("Letter"))
            .andHas(ex.iri("writtenBy"), legislate.iri("John"))
            .andHas(legislate.iri("writtenOn"), date);
    

    This is easier to read and shorter, and secondly, your use of default.iri("a") was incorrect (as an aside I don't even know how you have a Java variable called default because that's a reserved keyword and should result in a compilation error - so I've replaced with ex here).

    Putting it all together you'd get something like this:

    SelectQuery select = Queries.SELECT()
            .prefix(ex)
            .prefix(legislate)
            .select(countAgg.as(count))
            .where(GraphPatterns.and(longPattern)
                    .filter(Expressions.gt(date, nowFunc)));