Can I define a list of nodes so that I can use them as subject and object in a query - sparql

The following query searches all triplets where where the subject, object and relation are are elements of the set defined with ?sub, ?obj and ?rel.
select *
{
?sub ?rel ?obj
values (?sub) { ( wd:Q263 )( wd:Q328 )( wd:Q373 )( wd:Q14827288 ) }
values (?obj) { ( wd:Q263 )( wd:Q328 )( wd:Q373 )( wd:Q14827288 ) }
values (?rel) { ( wdt:P31 )( wdt:P361 )( wdt:P279 )( wdt:P527 ) }
}
Because values (?sub) ... and values (?obj) ... is redundant, I am wondering if there is a way to reformulate the query to use a list or subquery sp that it returns the same result, yet without having to repeat the list of wd:... identifiers.

Related

SPARQL degrees of separation

Using SPARQL, how can I find entities linked to an entity by x degrees of separation, for example 4 or 5 degrees? For example, with test data like this, how do I find which of my relatives connects to which one? The aim is to form a graph from the triples. (Using only “raised” as predicates in this example, but any connection should be considered.)
<http://www.example.com/great-grandma> <:raised1> <http://www.example.com/grandma> .
<http://www.example.com/grandma> <:raised2> <http://www.example.com/ma> .
<http://www.example.com/ma> <:raised3> <http://www.example.com/me> .
<http://www.example.com/ma> <:raised4> <http://www.example.com/sis> .
<http://www.example.com/me> <:raised5> <http://www.example.com/kid> .
<http://www.example.com/spouse> <:raised6> <http://www.example.com/kid> .
So from the above, the wanted first-degree relationships would be:
<http://www.example.com/ma> <:raised3> <http://www.example.com/me> .
<http://www.example.com/me> <:raised5> <http://www.example.com/kid> .
With the whole s-p-o triple as the result.
I can get to two degrees relatively easily:
SELECT *
WHERE
{ { SELECT DISTINCT ?s ?p ?o
WHERE
{ ?s ?p1 <http://www.example.com/me> .
?s ?p ?o
}
}
UNION
{ SELECT DISTINCT ?s ?p ?o
WHERE
{ <http://www.example.com/me> ?p1 ?o .
?s ?p ?o
}
}
UNION
{ SELECT DISTINCT ?s ?p ?o
WHERE
{ ?o ?p1 <http://www.example.com/me> .
?s ?p ?o
}
}
UNION
{ SELECT DISTINCT ?s ?p ?o
WHERE
{ <http://www.example.com/me> ?p1 ?s .
?s ?p ?o
}
}
}
This finds my grandmother and sister, for example. But this does not seem practical with more degrees of separation, as the number of sub-queries would double with each new degree. Is there a better way to do this? It would need to work with larger amounts of data too, so can't just run a new query on every linked entity.
EDIT: Highlighting that different predicates should be expected, I clarified and changed the example a bit.
Property paths are your friend.
SELECT DISTINCT ?rel {
{
SELECT ?rel {
:me (:raised|^:raised) ?rel
}
}
UNION {
SELECT ?rel {
:me (:raised|^:raised)/(:raised|^:raised) ?rel
}
}
UNION {
SELECT ?rel {
:me (:raised|^:raised)/(:raised|^:raised)/(:raised|^:raised) ?rel
}
}
}
and so on...

using a sparql query as a building block in another query

I can write a SPARQL query to concat words in a sentence found in individual triples to a single sentence:
SELECT ?sent (sample (?sf1) as ?sf11) (group_concat(?wf) as ?sf2)
WHERE
{ ?sent a nlp:Sentence .
{select *
{ ?w rdfs:partOf ?sent .
?w a nlp:Token .
?w nlp:wordForm ?wf .
} order by ?w
}
} group by ?sent
limit 20
but I cannot find a way to use this select statement in another query, where I find the sentence ?sent and would like to insert this select statement:
select *
where
{ ?tok a wn:Locomote.
?tok nlp:lemma3 ?lem .
?tok rdfs:partOf ?sent .
?sent a nlp:Sentence .
?werk ^rdfs:partOf ?sent .
{SELECT ?sent (group_concat(?wf) as ?sf2)
WHERE
{ ?sent a nlp:Sentence .
{select *
{ ?w rdfs:partOf ?sent .
?w a nlp:Token .
?w nlp:wordForm ?wf .
} order by ?w
}
} group by ?sent
}
}
The result is a not the sentence found in the first part, but it seems as ?sent in the nested query is not restricted by the outer query.
I do not see how to nest properly.
Thank you for help!
Example of custom aggregate in Jena:
package org.stackoverflow.jena.customaggregate;
import com.google.common.base.Joiner;
import org.apache.jena.atlas.logging.LogCtl;
import org.apache.jena.graph.Graph;
import org.apache.jena.query.*;
import org.apache.jena.rdf.model.ModelFactory;
import org.apache.jena.sparql.engine.binding.Binding;
import org.apache.jena.sparql.expr.Expr;
import org.apache.jena.sparql.expr.ExprEvalException;
import org.apache.jena.sparql.expr.ExprList;
import org.apache.jena.sparql.expr.NodeValue;
import org.apache.jena.sparql.expr.aggregate.Accumulator;
import org.apache.jena.sparql.expr.aggregate.AccumulatorFactory;
import org.apache.jena.sparql.expr.aggregate.AggCustom;
import org.apache.jena.sparql.expr.aggregate.AggregateRegistry;
import org.apache.jena.sparql.function.FunctionEnv;
import org.apache.jena.sparql.graph.NodeConst;
import org.apache.jena.sparql.sse.SSE;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class AggGroupConcatSorted {
static {
LogCtl.setCmdLogging();
}
static AccumulatorFactory accumulatorFactory = (agg, distinct) -> new AccGroupConcatSorted(agg);
static class AccGroupConcatSorted implements Accumulator {
private AggCustom agg;
private List<String> nodeStrList = new ArrayList<>();
AccGroupConcatSorted(AggCustom agg) {
this.agg = agg;
}
#Override
public void accumulate(Binding binding, FunctionEnv functionEnv) {
ExprList exprList = agg.getExprList();
for (Expr expr : exprList) {
try {
NodeValue nv = expr.eval(binding, functionEnv);
// Evaluation succeeded, add string to list
nodeStrList.add(nv.asString());
} catch (ExprEvalException ex) {
}
}
}
#Override
public NodeValue getValue() {
// sort list
Collections.sort(nodeStrList);
// return single node which in fact is the concatenated string of the list elements
return NodeValue.makeString(Joiner.on(" ").join(nodeStrList));
}
}
public static void main(String[] args) {
// Example aggregate that concatenates the node values in sorted order
String aggUri = "http://example.org/group_concat_sorted" ;
// register the custom aggregate - returns unbound for no rows
AggregateRegistry.register(aggUri, accumulatorFactory, NodeConst.nodeMinusOne);
// sample data
Graph g = SSE.parseGraph("(graph (:s :p \"b\") (:s :p \"bc\") (:s :p \"abc\"))") ;
String qs = "SELECT (<http://example.org/group_concat_sorted>(?o) AS ?x) {?s ?p ?o}" ;
// query execution
Query q = QueryFactory.create(qs) ;
try ( QueryExecution qexec = QueryExecutionFactory.create(q, ModelFactory.createModelForGraph(g)) ) {
ResultSet rs = qexec.execSelect() ;
ResultSetFormatter.out(rs);
}
}
}

Jena dbpedia how to use (STR(?foo) AS ?foo2)?

i want to avoid using substring to eliminate by example #en in my
ontology:abstract or ontology:label, it work with sparql explorer but when i use http query in jena it dont give any result... i tried this query in android project with jena library (androjena)
SELECT ?type (STR(?l) AS ?label) {
?type a owl:Class;
rdfs:label ?l .
FILTER (LANG(?l) = "en")
}
once i put this in my Jena httpquery (STR(?l) AS ?label)it dont give any result anymore. someone can help me?
here is the part of the code that i try to manage to change to avoid use of substrings :
private String entityQuery(String entity, String keyWord, String language) {
return addPrefix("rdfs: <http://www.w3.org/2000/01/rdf-schema#>") +
addPrefix("ontology: <http://dbpedia.org/ontology/>") +
addQuery("SELECT ?name ?desc ?thumb WHERE {\n"
+"?author a ontology:" + entity + ";\n"
+"rdfs:label ?name;\n"
+"ontology:abstract ?desc.\n"
+"FILTER(<bif:contains>(?desc,\"'"+keyWord+"'\") && langMatches(lang(?desc), \""+language+"\") " +
"&& langMatches( lang(?name), \""+language+"\"))\n"
+"OPTIONAL { ?author ontology:thumbnail ?thumb }.\n"
+"}ORDER BY ?name\n");
}
private LinkedList<Entity> collectEntities(ResultSet results) {
LinkedList<Entity> temp = new LinkedList<>();
/* do stuff with the results */
while (results.hasNext()) {
Entity a = new Entity();
QuerySolution row = results.next();
if (row.getResource("thumb") != null)
a.setPictureURL(row.get("thumb").toString());
a.setTitle(row.get("name").toString().substring(0, row.get("name").toString().indexOf("#")));
a.setSummary(row.get("desc").toString().substring(0, row.get("desc").toString().indexOf("#")));
temp.add(a);
}
return temp;
}
private String addPrefix(String prefix) {
return "PREFIX " + prefix + "\n";
}
private String addQuery(String query) {
return query;
}
i use substring here :
a.setTitle(row.get("name").toString().substring(0, row.get("name").toString().indexOf("#")));
a.setSummary(row.get("desc").toString().substring(0, row.get("desc").toString().indexOf("#")));

Generate SPARQL query for DBpedia giving distinct result

I am using SPARQL for querying the DBpedia database. My first query was the following:
select ?s1 ( bif:search_excerpt ( bif:vector ( 'TENDULKAR', 'SACHIN' ) , ?o1 ) ) where
{
{
{
select ?s1, ( ?sc * 3e-1 ) as ?sc, ?o1, ( sql:rnk_scale ( <LONG::IRI_RANK> ( ?s1 ) ) ) as ? rank, ?g where
{
quad map virtrdf:DefaultQuadMap
{
graph ?g
{
?s1 ?s1textp ?o1 .
?o1 bif:contains ' ( TENDULKAR AND SACHIN ) ' option ( score ?sc ) .
}
}
}
order by desc ( ?sc * 3e-1 + sql:rnk_scale ( <LONG::IRI_RANK> ( ?s1 ) ) ) limit 20 offset 0
}
}
}
Now even if I apply the DISTINCT keyword to the query it gives the same result as before.
I want distinct results from this query.

All-In-One Active Record get() method or ORM (PHP-Active Record)

Is a universal get() method like the one below a good idea
function universal_get( $select=NULL, $from=NULL, $where=NULL, $group=NULL, $having=NULL, $order=NULL, $limit=NULL )
{
// condition checks
if ( is_string( $select ) OR is_array ( $select )) { $this->db->select( $select ); }
if ( is_string( $from ) ) { $this->db->from( $from ); }
if ( is_array( $where ) ) { $this->db->where( $where ); }
if ( is_string( $group ) OR is_array( $group ) ) { $this->db->group_by( $group ); }
if ( is_array( $having ) ) { $this->db->having( $having ); }
if ( is_array( $order ) ) { $this->db->order_by( $order ); }
if ( is_string( $limit ) OR is_int( $limit ) ) { $this->db->limit( $limit ); }
$result = $this->db->get( $from );
if ( $result->num_rows() > 0 ) { return $result->result(); }
else { return FALSE; }
}
or would an ORM like PHP-ActiveRecord be a better option?
Thanks
Strait forward: No
If you are a programmer then write good code. When I started with CI I was making functions like these all over the place and it very confusing. CI is a framework so basically you are building a framework off of a framework.
Another thing to keep in mind is, you need to always know what going on in the code. Having functions that do too much cause bugs which are hard to trace and restrict usability to specific applications. For instance what if you want to use a join? All properly designed databases will use a join eventually.
I dont think thats a good idea. CI's Active Record takes care of things you dont want to deal with... Add slashes, chaining where and a few others.. just check out their class.
http://codeigniter.com/user_guide/database/active_record.html