Is it possible to easily make a CONSTRUCT request where I would be able to check data in different graphs AND sort them by "graph preference"?
Let's say I sell products. For each product, I may have different suppliers, so that my setup would look like this:
<http://data.experiment.com/product/1> <http://purl.org/goodrelations/v1#hasCurrencyValue> "10" <http://data.experiment.com/graph/supplier/1> .
<http://data.experiment.com/product/1> <http://purl.org/goodrelations/v1#hasCurrencyValue> "8" <http://data.experiment.com/graph/supplier/2> .
<http://data.experiment.com/product/2> <http://purl.org/goodrelations/v1#hasCurrencyValue> "5" <http://data.experiment.com/graph/supplier/2> .
For each product specification, I want it from <http://data.experiment.com/graph/supplier/1>, then from <http://data.experiment.com/graph/supplier/2> if not found in <http://data.experiment.com/graph/supplier/1>.
This is what I've come up to:
CONSTRUCT
{
<http://data.experiment.com/product/1> ?p ?o .
}
WHERE
{
GRAPH <http://data.experiment.com/graph/supplier/1>
{
OPTIONAL
{
<http://data.experiment.com/product/1> ?p1 ?o1 .
}
}
GRAPH <http://data.experiment.com/graph/supplier/2>
{
OPTIONAL
{
<http://data.experiment.com/product/1> ?p2 ?o2 .
}
}
BIND (IF (BOUND(?p1), ?p1, IF (BOUND(?p2), ?p2, UNDEF)) AS ?p)
BIND (IF (BOUND(?o1), ?o1, IF (BOUND(?o2), ?o2, UNDEF)) AS ?o)
}
It does work pretty nice if I know what I'm looking for. Now if I consider:
CONSTRUCT
{
<http://data.experiment.com/product/1> ?p ?o . ?o ?cp ?co
}
WHERE
{
GRAPH <http://data.experiment.com/graph/supplier/1>
{
OPTIONAL
{
<http://data.experiment.com/product/1> ?p1 ?o1 .
OPTIONAL { ?o1 ?cp1 ?co1 . }
}
}
GRAPH <http://data.experiment.com/graph/supplier/2>
{
OPTIONAL
{
<http://data.experiment.com/product/1> ?p2 ?o2 .
OPTIONAL { ?o2 ?cp2 ?co2 . }
}
}
BIND (IF (BOUND(?p1), ?p1,IF (BOUND(?p2), ?p2, UNDEF)) AS ?p)
BIND (IF (BOUND(?o1), ?o1,IF (BOUND(?o2), ?o2, UNDEF)) AS ?o)
BIND (IF (BOUND(?cp1), ?cp1,IF (BOUND(?cp2), ?cp2, UNDEF)) AS ?cp)
BIND (IF (BOUND(?co1), ?co1,IF (BOUND(?co2), ?co2, UNDEF)) AS ?co)
}
Sometimes it doesn't work because I explicitly BIND ?o, and ?o may not be an Object —
Virtuoso RDF01 Error Bad variable value in CONSTRUCT: "1532610063"
(tag 189 box flags 0) is not a valid subject, only object of a triple
can be a literal
I don't seem to find anyone trying to sort data by "graphs" and I'm struggling trying to find an "easy" way to do it.
I've tried with SELECT and FROM NAMED, but you've still to manually select data from the graph you want.
If anyone can help, it is more than welcome.
Thank you.
Update from my previous post. Each suppliers for a given Book are stored in a "default" graph.
# Named graph : http://data.books.com/default
#prefix book: <http://data.books.com/resource/Book/>
#prefix ns: <http://data.books.com/ns#>
book:8780953608758 ns:hasSupplier <http://data.books.com/supplier/Alpha> .
book:8780953608758 ns:hasSupplier <http://data.books.com/supplier/Beta> .
# Named graph : http://data.books.com/supplier/Alpha
#prefix book: <http://data.books.com/resource/Book/>
#prefix price: <http://data.books.com/resource/Price/>
#prefix gr: <http://purl.org/goodrelations/v1#>
#prefix dc: <http://purl.org/dc/terms/>
book:8780953608758 gr:hasPriceSpecification price:8780953608758_FR_EUR .
price:8780953608758_FR_EUR gr:hasCurrencyValue "10" .
book:8780953608758 dc:available 1447632000 .
# Named graph : http://data.books.com/supplier/Beta
#prefix book: <http://data.books.com/resource/Book/>
#prefix price: <http://data.books.com/resource/Price/>
#prefix gr: <http://purl.org/goodrelations/v1#>
#prefix dc: <http://purl.org/dc/terms/>
book:8780953608758 gr:hasPriceSpecification price:8780953608758_FR_USD .
price:8780953608758_FR_USD gr:hasCurrencyValue "8" .
book:8780953608758 dc:available 1547632000 .
The first subquery in the query bellow use the graph http://data.books.com/default to find and sort all our suppliers graphs for the book 8780953608758. It then matches another pattern against that graph.
PREFIX book: <http://data.bookeen.com/resource/Book/>
CONSTRUCT
{
book:8780953608758 ?p ?o . ?o ?cp ?co .
}
WHERE
{
{
SELECT ?supplier
FROM <http://data.books.com/default>
WHERE
{
VALUES (?supplier ?priority)
{
(<http://data.books.com/supplier/Beta> 1)
(<http://data.books.com/supplier/Alpha> 2)
}
book:8780953608758 <http://data.books.com/ns/hasSupplier> ?supplier.
}
ORDER BY ?priority
LIMIT 1
}
GRAPH ?supplier
{
book:8780953608758 ?p ?o .
OPTIONAL { ?o ?cp ?co . }
}
}
Related
Given three possible objects for triples, foaf:name, foaf:givenName, and foaf:familyName, where statements either have foaf:name or foaf:givenName + foaf:familyName, e.g.:
<uri1> <foaf:name> "Lolly Loozles" .
<uri2> <foaf:givenName> "Stotly" .
<uri2> <foaf:familyName> "Styles" .
wondering how to write a SPARQL query to return a new variable like pretty_name that is either the value of foaf:name or a concatenation of the values from foaf:givenName and foaf:familyName.
Resulting in something like:
?o | ?pretty_name
----------------------
<uri1> | Lolly Loozles
<uri2> | Stotly Styles
This is what I have so far, but unsure how to proceed:
PREFIX : <https://example.org/>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
# select two variables, not ideal...
SELECT ?foaf_fullName ?pretty_name
WHERE {
# Find all triples
?s ?p ?o .
# Binds
OPTIONAL { ?s foaf:name ?foaf_fullName }
OPTIONAL { ?s foaf:givenName ?givenName }
OPTIONAL { ?s foaf:familyName ?familyName }
# Filter where predicate is part of list
FILTER (?p IN (foaf:name, foaf:givenName, foaf:familyName ) )
# Binds
BIND( CONCAT(?givenName, ' ', ?familyName) AS ?pretty_name ) .
}
I had imagined, and tried, adding another BIND to add to ?pretty_name, but the SPARQL engine wouldn't have it:
BIND( ?foaf_fullName AS ?pretty_name ) .
I also had luck writing a CONSTRUCT statement to get the values I'm looking for, but don't have the ability to write back to this triplestore (for a number of reasons):
CONSTRUCT {
?s :hasPrettyName ?foaf_fullName .
?s :hasPrettyName ?pretty_name .
}
I had thought that CONSTRUCT could accompany SELECT, but must have been mistaken?
Any insight or suggestions would much appreciated.
Using #StanislavKralin comment/suggestion to use COALESCE without IF clauses works great:
PREFIX : <https://example.org/>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
# select two variables, not ideal...
SELECT ?foaf_fullName ?pretty_name
WHERE {
# Find all triples
?s ?p ?o .
# Binds
OPTIONAL { ?s foaf:name ?foaf_fullName }
OPTIONAL { ?s foaf:givenName ?givenName }
OPTIONAL { ?s foaf:familyName ?familyName }
# Filter where predicate is part of list
FILTER (?p IN (foaf:name, foaf:givenName, foaf:familyName ) )
# Binds
BIND( COALESCE(?foaf_fullName, CONCAT(?givenName, ' ', ?familyName)) AS ?pretty_name )
}
I'm trying to return subjects based on the relative position of their subjects in an ordered list.
A subject can be associated with multiple objects (via a single predicate) and all objects are in an ordered list. Given a reference object in this list I'd like to return the subjects in order of relative distance of their objects from the reference object.
:a : :x
:b : :v
:b : :z
:c : :v
:c : :y
:ls :list (:v :w :x :y :z)
Taking x as our starting object in the list, the code below returns
:a :x :0
:c :y :1
:b :v :2
:b :z :2
:c :v :2
Instead of returning all positions I would like only the objects relating to the subject's minimum object 'distance' to be returned (which may mean up to two objects per subject - both up and down the list). So I'd like to return
:a :x :0
:c :y :1
:b :v :2
:b :z :2
The code so far...
(with a lot of help from Find lists containing ALL values in a set? and Is it possible to get the position of an element in an RDF Collection in SPARQL?)
SELECT ?s ?p (abs(?refPos-?pos) as ?dif)
WHERE {
:ls :list/rdf:rest*/rdf:first ?o .
?s : ?o .
{
SELECT ?o (count(?mid) as ?pos) ?refPos
WHERE {
[] :list/rdf:rest* ?mid . ?mid rdf:rest* ?node .
?node rdf:first ?o .
{
SELECT ?o (count(?mid2) as ?refPos)
WHERE {
[] :list/rdf:rest* ?mid2 . ?mid2 rdf:rest* ?node2 .
?node2 rdf:first :x .
}
}
}
GROUP BY ?o
}
}
GROUP BY ?s ?o
ORDER BY ?dif
I've been trying to get a minimum ?dif (difference/distance) by grouping by ?s but because I then have to apply this (something like ?dif = ?minDif) to the ?s ?o grouping from earlier I don't know how to go back and forward between these two groupings.
Thanks for any assistance you can provide
All you needed to compound a solution is yet another one Joshua Taylor's answer: this or this.
Here below I'm using Jena functions, but I hope the idea is clear.
Query 1
PREFIX list: <http://jena.hpl.hp.com/ARQ/list#>
SELECT ?s ?el ?dif {
?s : ?el .
:ls :list/list:index (?pos ?el) .
:ls :list/list:index (?ref :x) .
BIND (ABS(?pos -?ref) AS ?dif)
{
SELECT ?s (MIN (?dif_) AS ?dif) WHERE {
?s : ?el_ .
:ls :list/list:index (?pos_ ?el_) .
:ls :list/list:index (?ref_ :x) .
BIND (ABS(?pos_ - ?ref_) AS ?dif_)
} GROUP by ?s
}
}
Query 2
PREFIX list: <http://jena.apache.org/ARQ/list#>
SELECT ?s ?el ?dif {
?s : ?el .
:ls :list/list:index (?pos ?el) .
:ls :list/list:index (?ref :x) .
BIND (ABS(?pos -?ref) AS ?dif)
FILTER NOT EXISTS {
?s : ?el_ .
:ls :list/list:index (?pos_ ?el_) .
BIND (ABS(?pos_ - ?ref) AS ?dif_) .
FILTER(?dif_ < ?dif)
}
}
Update
Query 1 can be rewritten in this way:
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
SELECT ?s ?el ?dif {
?s : ?el
{ select (count(*) as ?pos) ?el {[] :list/rdf:rest*/rdf:rest*/rdf:first ?el} group by ?el }
{ select (count(*) as ?ref) {[] :list/rdf:rest*/rdf:rest*/rdf:first :x} }
BIND (ABS(?pos - ?ref) AS ?dif)
{
SELECT ?s (MIN(?dif_) AS ?diff) {
?s : ?el_
{ select (count(*) as ?pos_) ?el_ {[] :list/rdf:rest*/rdf:rest*/rdf:first ?el_} group by ?el_ }
{ select (count(*) as ?ref_) {[] :list/rdf:rest*/rdf:rest*/rdf:first :x} }
BIND (ABS(?pos_ - ?ref_) AS ?dif_)
} GROUP by ?s
}
FILTER (?dif = ?diff)
}
Notes
As you can see, this is not what SPARQL was designed for. For example, Blazegraph supports Gremlin...
Possibly this is not what RDF was designed for. Or try other modeling approach: do you really need RDF lists?
I haven't tested the above query in Virtuoso.
I need a sparql query that given a free text (user input),
it finds me from dbpedia all the classes related to it.
How do it?
Also asked here. Accepted answer said --
When you say classes, are you mean about types? If yes, try something like
SELECT ?uri ?label ?type
WHERE {
?uri rdfs:label ?label .
?uri <http://dbpedia.org/ontology/type> ?type .
FILTER regex(str(?label), "Leipzig") .
}
limit 10
I couldn't let this go...
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX virtdrf: <http://www.openlinksw.com/schemas/virtrdf#>
SELECT ?s1c AS ?c1
COUNT (*) AS ?c2
?c3
WHERE
{
QUAD MAP virtrdf:DefaultQuadMap
{
GRAPH ?g
{
?s1 ?s1textp ?o1 .
?o1 bif:contains '"dbpedia"' .
}
}
?s1 a ?s1c .
OPTIONAL { ?s1c rdfs:label ?c3
FILTER(langMatches(LANG(?c3),"EN"))}
}
GROUP BY ?s1c ?c3
ORDER BY DESC (2) ASC (3)
The earlier answer gets you partial results.
I have a Fuseki DB with triples like the following:
<https://tomcat.antudo.it/data/bucket.json-WSP1WS8#row=1>
<https://tomcat.antudo.it/data/bucket.json-WSP1WS8#ws7col0>
"ws6dat1aa"
...
<https://tomcat.antudo.it/data/bucket.json-WSP1WS8#row=2>
<https://tomcat.antudo.it/data/bucket.json-WSP1WS8#ws6col2>
"ws6dat2aa"
...
<http://www.w3.org/2002/07/owl#bottomDataProperty>
<http://www.w3.org/2002/07/owl#propertyDisjointWith>
<https://tomcat.antudo.it/data/bucket.json-WSP1WS8#ws7col0>
I want to delete everything related to:
<https://tomcat.antudo.it/data/bucket.json-WSP1WS8#row=1>
The problem is that i'm not able to write a query that also target triples like that one:
<http://www.w3.org/2002/07/owl#bottomDataProperty>
<http://www.w3.org/2002/07/owl#propertyDisjointWith>
<https://tomcat.antudo.it/data/bucket.json-WSP1WS8#ws7col0>
I have used the following query to delete triples about a list of entities:
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
DELETE {
?x ?y ?z
}
WHERE {
{
?x ?y ?z.
?x rdfs:seeAlso <https://tomcat.antudo.it/data/#dcat_test.csv-WSP1WS6>.
}
union
{
?x ?y ?z.
?x rdfs:seeAlso <https://tomcat.antudo.it/data/#dcat_test.csv-WSP1WS7>.
}
}
I think i have to do something similar to that:
SPARQL: Delete instance and all of its properties with linked subproperties but i'm stuck. Any help will be appreciated
The following should work if you want to delete the resource entirely from the graph. Note that you need to remove the triples "both ways".
DELETE {
<https://tomcat.antudo.it/data/bucket.json-WSP1WS8#row=1> ?p ?o .
?s1 ?p1 <https://tomcat.antudo.it/data/bucket.json-WSP1WS8#row=1> .
}
WHERE {
<https://tomcat.antudo.it/data/bucket.json-WSP1WS8#row=1> ?p ?o .
OPTIONAL {
?s1 ?p1 <https://tomcat.antudo.it/data/bucket.json-WSP1WS8#row=1> .
}
}
Given the graph http://example.org/ as:
#prefix foaf:<http://xmlns.com/foaf/0.1/purl>.
<uri:alice> foaf:name "Alice".
<uri:bob> foaf:name "Bob".
<uri:carl> foaf:name "Carl".
Why this SPARQL query works:
PREFIX foaf:<http://xmlns.com/foaf/0.1/purl>
SELECT *
WHERE {
GRAPH <http://example.org/> {
?model_ic foaf:name ?name.
FILTER (?name = "Bob")
}
}
Whereas this one don't (well, technically it works but returns 0 matches)
PREFIX foaf:<http://xmlns.com/foaf/0.1/purl>
SELECT *
WHERE {
GRAPH <http://example.org/> {
?model_ic foaf:name "Bob".
}
}
If there is any other attachment to the name rather only the string you might have issues. For example, foaf:name normally has a language attached. Try:
PREFIX foaf:<http://xmlns.com/foaf/0.1/purl>
SELECT *
WHERE {
GRAPH <http://example.org/> {
?model_ic foaf:name "Bob"#en.
}
}