Changing a query to return graph name as well

Hi,

Bachground

We've been interacting with stardog and executing our SELECT queries using a code snippet like below.


      String sparql = "SELECT * WHERE {?s ?p ?o}"         
      Dataset dataset = Datasets.builder().defaultGraphs(listResources).build();
      SelectQuery query = connection.select(sparql).dataset(dataset);
      //query.parameter(arg.getKey(), arg.getValue());
          ArrayList<Map<String, Object>> list = new ArrayList<>();
          result = query.execute();
         while (result.hasNext()) {
           list.add(mapper.mapRow(result.next()));
         }     
 // The rest 

In this code dataset is a list of graphs that we want to execute our query against them.

Problem

Now, we've decided to get name of the graph along with the result of our queries. For instance, for the above dummy sparql query, we're interested to get the graph name of each triple.

Questions

  • What do you suggest to do so?
    One way might be doing some text processing over all our existing queries using regex and modify them. For instance, the above dummy query is gonna be sparql = "SELECT * WHERE { GRAPH ?g {?s ?p ?o}}" and then execute it. Then, we're not sure whether we need to manually add FROM NAMED to each query or we can still use dataset.
  • Do you think it is a good approach to do this?
  • Do you have any smarter suggestion to do it (e.g., using JAVA SNARL package's potential methods)?

It would be great if you could share your thoughts and suggestions with us. Thank you.

Hi Cesar,

If you want the graph IRI for each triple, then your query pattern has to be graph ?g { ?s ?p ?o }, as you thought. No need to add FROM NAMED to the query string if you change your dataset to use namedGraphs instead of defaultGraphs.

You can read more on the relationship between FROM/NAMED and GRAPH in our blog post: FROM vs FROM NAMED in SPARQL

Cheers,
Pavel

1 Like

Hi @pavel

Thank you for your reply. We've implemented the suggested approach to modify our queries, but we're now encountering kind of BINDing problem for majority of our queries. For instance, we had query like this

SELECT DISTINCT  ?Acc ?Held_By ?Organisation ?Cap
WHERE {    
   BIND(?this AS ?that)
    ?Cap (rdfs:subClassOf)* ?that
    OPTIONAL
      { ?Cap C:deleToOrg ?Organisation
        OPTIONAL
          { ?Pos V:manages ?Organisation .
            ?Pos V:occupyingRole ?Acc .
            ?Pos V:heldBy ?Held_By
          }
      }
  }

we modified it to:

SELECT DISTINCT  ?graph ?Acc ?Held_By ?Organisation ?Cap

WHERE { GRAPH ?graph {
      BIND(?this AS ?that)
    ?Cap (rdfs:subClassOf)* ?that
    OPTIONAL
      { ?Cap C:deleToOrg ?Organisation
        OPTIONAL
          { ?Pos V:manages ?Organisation .
            ?Pos V:occupyingRole ?Acc .
            ?Pos V:heldBy ?Held_By
          }
      }
  }
}

When we use Stardog studio and a manual BIND like BIND(<example.com/input1> AS ?this) to it and run it, it works properly and return the expected number of results. But when we use SNARL to bind (by using query.parameter) it and execute it through our JAVA code, it is executed but BINDing is not applied. Even query explain shows that the BIND is applied but seems that it does not affect


# reused
From named <XXXX1>
From named <XXXX2>
From named <XXXX3>
From named <XXXX4>
Distinct [#271K]
`─ Projection(?graph, ?Acc, ?Held_By, ?Organisation, ?Cap) [#271K]
   `─ MergeJoinOuter(?Capability) [#271K]
      +─ Bind(<example.com/input1> AS ?this) sortedBy=?Cap [#271K]
      │  `─ PropertyPath(?Cap -> ?that in ?graph, minLength=0, sortedBy=?Cap) [#271K]
      │     `─ Scan[PSOC](?Cap, rdfs:subClassOf, ?that){?graph} [#11K]
      `─ HashJoinOuter(?Organisation) [#133]
         +─ Scan[PSOC](?Cap, <http://x.com/core/C#deleToOrg>, ?Organisation){?graph} [#133]
         `─ NaryJoin(?Pos) [#23]
            +─ Scan[PSOC](?Pos, <http://x.com/core/V#heldBy>, ?Held_By){?graph} [#55]
            +─ Scan[PSOC](?Pos, <http://x.com/core/V#manages>, ?Organisation){?graph} [#29]
            `─ Scan[PSOC](?Pos, <http://x.com/core/V#occupyingRole>, ?Acc){?graph} [#63]

On the other hand, Stardog studio Plan (and Profiler) is as follows

From named <XXXX1>
From named <XXXX2>
From named <XXXX3>
From named <XXXX4>
Slice(offset=0, limit=1000) [#2], results: 11, wall time: 0 ms (0.0%)
`─ Distinct [#2], memory: {total=256K (30.8%); max=224K}, results: 11, wall time: 2 ms (4.7%)
   `─ Projection(?graph, ?Acc, ?Held_By, ?Organisation, ?Cap) [#2], results: 11, wall time: 0 ms (0.0%)
      `─ MergeJoinOuter(?Cap) [#2], results: 11, wall time: 2 ms (4.7%)
         +─ Sort(?Cap) [#2], memory: {total=256K (30.8%)}, results: 11, wall time: 2 ms (4.7%)
         │  `─ MergeJoin(?that) [#2], results: 11, wall time: 1 ms (2.3%)
         │     +─ Bind(example.com/input1 AS ?this) (example.com/input1 ?that) sortedBy=?that [#1], results: 1, wall time: 0 ms (0.0%)
         │     `─ PropertyPath(?Cap -> ?that in ?graph, minLength=0, sortedBy=?that, reversed) [#11], results: 11 (with gaps), wall time: 6 ms (14.0%)
         │        +─ Bind(example.com/input1 AS ?that) sortedBy=?that [#1], results: 1 (with gaps), wall time: 0 ms (0.0%)
         │        `─ Scan[POSC](?Cap, http://www.w3.org/2000/01/rdf-schema#subClassOf, ?that){?graph} [#11K]
         `─ HashJoinOuter(?Organisation) [#133], memory: {total=320K (38.5%); max=288K}, results: 7 (with gaps), wall time: 1 ms (2.3%)
            +─ Scan[PSOC](?Cap,http://x.com/core/C#deleToOrg, ?Organisation){?graph} [#133], results: 8 (with gaps), wall time: 1 ms (2.3%)
            `─ NaryJoin(?Pos) [#23], results: 21, wall time: 7 ms (16.3%)
               +─ Scan[PSOC](?Pos, http://x.com/core/V#heldBy, ?Held_By){?graph} [#55], results: 36 (with gaps), wall time: 1 ms (2.3%)
               +─ Scan[PSOC](?Pos, http://x.com/core/V#manages, ?Organisation){?graph} [#29], results: 31 (with gaps), wall time: 0 ms (0.0%)
               `─ Scan[PSOC](?Pos, http://x.com/core/V#occupyingRole, ?Acc){?graph} [#63], results: 39 (with gaps), wall time: 1 ms (2.3%)

Plans are different, I'm not sure what's going on here. Maybe we're not using SNARL properly or something else. It would be appreciated if you can share your thoughts with us on this. It may worth nothing that before using named graphs, the same with the same binding approach from java worked fine. Thank you

Why can't you just use this basic query (without an additional BIND):

SELECT DISTINCT  ?graph ?Acc ?Held_By ?Organisation ?Cap

WHERE { GRAPH ?graph {
    ?Cap (rdfs:subClassOf)* ?that
    OPTIONAL
      { ?Cap C:deleToOrg ?Organisation
        OPTIONAL
          { ?Pos V:manages ?Organisation .
            ?Pos V:occupyingRole ?Acc .
            ?Pos V:heldBy ?Held_By
          }
      }
  }
}

and then do .parameter("that", Values.iri("example.com/input1"))? That should work.

Cheers,
Pavel