st_within function of GeoSPARQL on Virtuoso - virtuoso

I installed Virtuoso Open Source Edition 07.20.3217.
But GeoSPARQL does not work as I expected.
I inserted 10 triples --
prefix owl: <http://www.w3.org/2002/07/owl#>
prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>
prefix geo: <http://www.opengis.net/ont/geosparql#>
prefix ex: <http://www.example.org/POI#>
prefix sf: <http://www.opengis.net/ont/sf#>
prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
ex:WashingtonMonument
rdf:type ex:Monument
rdfs:label "Washington Monument" ;
geo:hasGeometry ex:WMPoint .
ex:WMPoint
rdf:type sf:Point ;
geo:asWKT "POINT(-77.03524 38.889468)"^^geo:wktLiteral .
ex:NationalMall
a ex:Park ;
rdfs:label "National Mall" ;
geo:hasGeometry ex:NMPoly .
ex:NMPoly
a sf:Polygon ;
geo:asWKT "POLYGON((-77.050125 38.892086, -77.039482 38.892036, -77.039482 38.895393, -77.033669 38.895508, -77.033585 38.892052, -77.031906 38.892086, -77.031883 38.887474, -77.050232 38.887142, -77.050125 38.892086 ))"^^geo:wktLiteral .
Then I tried this GeoSPARQL query --
PREFIX geo: <http://www.opengis.net/ont/geosparql#>
SELECT *
WHERE {
?m geo:hasGeometry ?mgeo .
?p geo:hasGeometry ?pgeo .
FILTER (bif:st_within(?mgeo, ?pgeo))
}
But there is no result.
What did I do wrong?
Thank you for any response.

I think you might want to specify that you're looking for Monuments within Parks. Also, I don't think you want a wildcard result, but only the list of such Monuments and Parks.
PREFIX geo: <http://www.opengis.net/ont/geosparql#>
SELECT ?monument
?park
WHERE
{
?monument a ex:Monument ;
geo:hasGeometry ?mgeo .
?park a ex:Park ;
geo:hasGeometry ?pgeo .
FILTER (bif:st_within(?mgeo, ?pgeo))
}
Live examples are often more useful than hypotheticals, so here's an adjusted query that does produce results, though there seems to be an issue with Monument vs Park designation, and both have POINT geometry (i.e., no POLYGON data) --
PREFIX geo: <http://www.opengis.net/ont/geosparql#>
PREFIX lgdo: <http://linkedgeodata.org/ontology/>
PREFIX wgs: <http://www.w3.org/2003/01/geo/wgs84_pos#>
SELECT ?monument ?mlabel ?mgeo
?park ?plabel ?pgeo
WHERE
{
?monument a lgdo:Monument ;
rdfs:label ?mlabel ;
wgs:geometry ?mgeo .
?park a lgdo:Park ;
rdfs:label ?plabel ;
wgs:geometry ?pgeo .
FILTER (bif:st_within(?mgeo, ?pgeo))
}
I do not have time to find a live dataset that includes POLYGON geometry for Parks, and accurately places Monument POINTs within such Park POLYGONs, so I cannot dig much further ... but if you can make your instance public, or point to a live public instance that holds such data, we can go further.

Related

Get the complete info of a Wikidata item

I'm using the following query to get the info of a specific Wikidata item.
For example, this one gets the info about the movie Titanic
SELECT ?wd ?wdLabel ?ps ?ps_Label ?wdpqLabel ?pq_Label {
VALUES (?film) {(wd:Q44578)}
?film ?p ?statement .
?statement ?ps ?ps_ .
?wd wikibase:claim ?p.
?wd wikibase:statementProperty ?ps.
OPTIONAL {
?statement ?pq ?pq_ .
?wdpq wikibase:qualifier ?pq .
}
SERVICE wikibase:label { bd:serviceParam wikibase:language "en" }
} ORDER BY ?wd ?statement ?ps_
It works well and I do get the info, but I want to add the items ("Q") beside them.
For example, if the genre is "romance film" I would like to get Q1054574 besides it. And if the actor is Leonardo DiCaprio I would like to get Q38111.
How can I achieve this in this kind of query?
You could add ?ps_ to the SELECT:
SELECT ?wd ?wdLabel ?ps ?ps_Label ?ps_ ?wdpqLabel ?pq_Label
Result: Screenshot

How to restrict units in property shapes?

I'm looking to make some SHACL shapes for certain properties in my ontology that have a speicified unit. Example:
My instance data would look something like this:
otlc:surgeprotector_1
rdf:type otlc:Surgeprotector ;
otlc:Nominal_voltage[
rdf:type otlc:QuantityValue ;
rdf:value "225"^^xsd:float ;
otlc:hasUnit unit:KiloV ;
] ;
.
I then have some shapes to validate this data:
otlc:Nominal_voltageShape
rdf:type sh:PropertyShape ;
sh:path otlc:Nominal_voltage ;
sh:class otlc:QuantityValue ;
**otlc:hasUnit unit:KiloV ;**
sh:maxCount 1 ;
sh:minCount 1 ;
.
otlc:SurgeprotectorShape
rdf:type sh:NodeShape ;
sh:property otlc:Nominal_voltageShape ;
sh:targetClass otlc:Surgeprotector ;
.
My question: How can I specify the unit given for the predicate "otlc:hasUnit" in the instance data for each property in my ontology? My desired end result is to have a nodeshape for the surgeprotector, and a propertyshape for the property "nominal_voltage", to restrict the value for nominal_voltage to unit:KiloV. I'm hoping there is some kind of shacl keyword I had not heard of/realized I can use here, to add onto my propertyshape (right now, i put in what I would imagine exists for shacl in **). (for example, sh:pattern can be used to specify the value with regex, but I want to specify the value of a piece of metadata of my value, if that makes sense...)
Thanks in advance!
Robin
I believe you can replace your highlighted line with
sh:property [
sh:path otlc:hasUnit ;
sh:hasValue unit:KiloV ;
] ;
This would mean that this property shape must apply to all values of the surrounding property shape, i.e. all values of otlc:Nominal_voltage.
Alternative, you could use a path expression in a property shape one level higher up, e.g.
otlc:SurgeprotectorShape
...
sh:property [
sh:path ( otlc:Nominal_voltage otlc:hasUnit ) ;
sh:hasValue unit:KiloV ;
] ;
Note that sh:hasValue also implies sh:minCount 1, i.e. the value must be present. You may want to add sh:maxCount 1 as extra protection.

Why does SPARQL query take 30x as long in R package than on Land Registry?

When I run the following SPARQL query on the Land Registry console it takes c.0.4 seconds and returns all 2599 results:
prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>
prefix ukhpi: <http://landregistry.data.gov.uk/def/ukhpi/>
SELECT
?stripped_regionName ?stripped_date ?ukhpi ?avprice ?volume ?newbuildvolume ?regionName ?regionId ?region
WHERE
{
VALUES ?regionId {<http://landregistry.data.gov.uk/id/region/southampton> <http://landregistry.data.gov.uk/id/region/london> <http://landregistry.data.gov.uk/id/region/england> <http://landregistry.data.gov.uk/id/region/wales> <http://landregistry.data.gov.uk/id/region/scotland> <http://landregistry.data.gov.uk/id/region/barking> <http://landregistry.data.gov.uk/id/region/southwark> <http://landregistry.data.gov.uk/id/region/westminster> <http://landregistry.data.gov.uk/id/region/merton> <http://landregistry.data.gov.uk/id/region/greenwich> <http://landregistry.data.gov.uk/id/region/camden>}
?region ukhpi:refRegion ?regionId .
?region ukhpi:refMonth ?date .
?region ukhpi:housePriceIndex ?ukhpi .
?region ukhpi:averagePrice ?avprice .
?region ukhpi:salesVolume ?volume .
?region ukhpi:salesVolumeNewBuild ?newbuildvolume .
?regionId rdfs:label ?regionName
FILTER (langMatches( lang(?regionName), "EN") ) .
BIND (STR(?regionName) AS ?stripped_regionName) .
BIND (STR(?date) AS ?stripped_date) .
}
When I run the same query using the SPARQL package for R, it takes c.15.0 seconds to return all 2599 results:
endpoint <- "https://landregistry.data.gov.uk/landregistry/query"
query <- '
prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>
prefix ukhpi: <http://landregistry.data.gov.uk/def/ukhpi/>
SELECT
?stripped_regionName ?stripped_date ?ukhpi ?avprice ?volume ?newbuildvolume ?regionName ?regionId ?region
WHERE
{
VALUES ?regionId {<http://landregistry.data.gov.uk/id/region/southampton> <http://landregistry.data.gov.uk/id/region/london> <http://landregistry.data.gov.uk/id/region/england> <http://landregistry.data.gov.uk/id/region/wales> <http://landregistry.data.gov.uk/id/region/scotland> <http://landregistry.data.gov.uk/id/region/barking> <http://landregistry.data.gov.uk/id/region/southwark> <http://landregistry.data.gov.uk/id/region/westminster> <http://landregistry.data.gov.uk/id/region/merton> <http://landregistry.data.gov.uk/id/region/greenwich> <http://landregistry.data.gov.uk/id/region/camden>}
?region ukhpi:refRegion ?regionId .
?region ukhpi:refMonth ?date .
?region ukhpi:housePriceIndex ?ukhpi .
?region ukhpi:averagePrice ?avprice .
?region ukhpi:salesVolume ?volume .
?region ukhpi:salesVolumeNewBuild ?newbuildvolume .
?regionId rdfs:label ?regionName
FILTER (langMatches( lang(?regionName), "EN") ) .
BIND (STR(?regionName) AS ?stripped_regionName) .
BIND (STR(?date) AS ?stripped_date) .
}'
qd <- SPARQL(endpoint, query)
hpi_df <- qd$results
Is there a way to speed up the query when run through R, or is the delay unavoidable? I'm hoping there is a fix, but imagine it could be because the Land Registry console is always connected, but my R query needs to connect to the server first.
Just to answer this one, as far as I can see it does appear to be the R package that is slow.
My way around it was to download all the data and pre-load this, then create a function to only query and add new data each time someone loads up the app.
Filtering the data returned by the query to the minimum fields needed also helped.

Querying a vector of strings to Wikidata using WikidataQueryServiceR

Provided a vector of movies' names, I would like to know their genres querying Wikidata.
Since I am a R user, I have recently discovered WikidataQueryServiceR which has exactly the same example I was looking for:
library(WikidataQueryServiceR)
query_wikidata('SELECT DISTINCT
?genre ?genreLabel
WHERE {
?film wdt:P31 wd:Q11424.
?film rdfs:label "The Cabin in the Woods"#en.
?film wdt:P136 ?genre.
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}')
## 5 rows were returned by WDQS
Unfortunately, this query uses a static text, so I would like to replace The Cabin in the Woods by a vector. In order to do, I tried with the following code:
library(WikidataQueryServiceR)
example <- "The Cabin in the Woods" # Single string for testing purposes.
query_wikidata(paste('SELECT DISTINCT ?human ?humanLabel ?sex_or_gender ?sex_or_genderLabel WHERE {
?human wdt:P31 wd:Q5.
?human rdfs:label', example, '#en.
?human wdt:P21 ?sex_or_gender.
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
OPTIONAL { ?human wdt:P2561 ?name. }
}', sep = ""))
But that does not work as expected, as I get the following result:
Error in FUN(X[[i]], ...) : Bad Request (HTTP 400).
What am I doing wrong?
Have you tried to output your SPARQL query? —
There is no space after rdfs:label
There are no quotes around The Cabin in the Woods
In your R code, instead of
?human rdfs:label', example, '#en.
line 7 should be:
?human rdfs:label "', example, '"#en.
Although query_wikidata() can accept vector of strings, I'd suggest to use SPARQL 1.1 VALUES instead, in order to avoid too many requests.
library(WikidataQueryServiceR)
example <- c("John Lennon", "Paul McCartney")
values <- paste(sprintf("('%s'#en)", example), collapse=" ")
query <- paste(
'SELECT DISTINCT ?label ?human ?humanLabel ?sexLabel {
VALUES(?label) {', values,
'}
?human wdt:P31 wd:Q5.
?human rdfs:label ?label.
?human wdt:P21 ?sex.
SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}'
)
query_wikidata(query)
For large number of VALUES, you probably need to use the development verion of WikidataQueryServiceR: it seems that only the development version supports POST requests.

Static content before loop

Am new to XQuery. I have written below query which is working perfectly and producing results in csv format from an
xml stored in Marklogic.
xquery version "0.9-ml"
let $data := someQuery
return
for $i in $data
return
fn:string-join((
$i/PATHTOFILED_1/text(),
$i/PATHTOFILED_2/text(),
.
.
.
.
$i/PATHTOFILED_N/text()
),","
)
Output:
abc,def,adc,
dff,eef,ddf,
.
.
.
.
fff,eed,ddg,
I have a new requirement to add static headers before the data.
And the expected output will be like
Expected Output:
HEAD1, HEAD2, HEAD3,
abc,def,adc,
dff,eef,ddf,
.
.
.
.
fff,eed,ddg,
Just adding HEAD1, HEAD2, HEAD3, in the top row. The headers are not part of the XML. They should be part of query in simple Strings with static data and can be modified at anytime in query itself.
I have tried to add the below code segment to the query. But the query is not running in Marklogic query console.
concat("HEAD1,"HEAD2","HEAD3"),
Any solution is highly appreciated.
Thanks in advance.
Add it before the FLWOR expression:
xquery version "1.0-ml";
string-join(("HEAD1","HEAD2","HEAD3"),","),
let $data := someQuery
return
for $i in $data
return
fn:string-join((
$i/PATHTOFILED_1/text(),
$i/PATHTOFILED_2/text(),
.
.
.
.
$i/PATHTOFILED_N/text()
),","
)
BTW, I really wouldn't use to 0.9-ml dialect unless you have a very compelling reason to do so. It works, but it is really only still there for compatibility.

Resources