问题
Using http://www.sparql.org/sparql.html to run this query
prefix oxprop: <http://ophileon.com/ox/property#>
prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>
prefix owl: <http://www.w3.org/2002/07/owl#>
prefix wgs84_pos: <http://www.w3.org/2003/01/geo/wgs84_pos#>
prefix gn: <http://www.geonames.org/ontology#>
select *
from <http://www.ophileon.com/ox/poi.rdf>
where
{
?poi rdfs:label ?poiname.
?poi owl:sameAs ?geonameuri.
SERVICE <http://factforge.net/sparql>{
?geonameuri gn:population ?population.
}
FILTER(langMatches(lang(?poiname), "EN")).
}
returns
-------------------------------------------------------------------------------------------------------
| poi | poiname | geonameuri | population |
=======================================================================================================
| <http://ophileon.com/ox/poi/2> | "Wageningen"@en | <http://sws.geonames.org/2745088/> | "35433" |
| <http://ophileon.com/ox/poi/3> | "Netherlands"@en | <http://sws.geonames.org/2750405/> | "16645000" |
| <http://ophileon.com/ox/poi/1> | "Amsterdam"@en | <http://sws.geonames.org/2759794/> | "767457" |
| <http://ophileon.com/ox/poi/1> | "Amsterdam"@en | <http://sws.geonames.org/2759794/> | "741636" |
-------------------------------------------------------------------------------------------------------
i.e. with multiple values for population. Apparently coming from different graphs that factforge is querying. Is there a way to limit or prioritize factforge to for instance the geonames graph ? BTW, geonames does not provide an open SPARQL endpoint, that's why I'm using Factforge.
回答1:
Let's start by changing your query just a little bit. Let's force ?poiname
to be "Amsterdam"@en
, so that we're only getting the problematic results:
prefix oxprop: <http://ophileon.com/ox/property#>
prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>
prefix owl: <http://www.w3.org/2002/07/owl#>
prefix wgs84_pos: <http://www.w3.org/2003/01/geo/wgs84_pos#>
prefix gn: <http://www.geonames.org/ontology#>
select *
from <http://www.ophileon.com/ox/poi.rdf>
where
{
values ?poiname { "Amsterdam"@en }
?poi rdfs:label ?poiname.
?poi owl:sameAs ?geonameuri.
SERVICE <http://factforge.net/sparql> {
?geonameuri gn:population ?population.
}
FILTER(langMatches(lang(?poiname), "EN")).
}
SPARQL results
Now, we can wrap the query that's in the service
block inside graph ?g { ... }
to find out where those triples are coming from. That is, we now have:
SERVICE <http://factforge.net/sparql> {
graph ?g { ?geonameuri gn:population ?population. }
}
SPARQL results
----------------------------------------------------------------------------------------------------------------------------
| poiname | poi | geonameuri | population | g |
============================================================================================================================
| "Amsterdam"@en | <http://ophileon.com/ox/poi/1> | <http://sws.geonames.org/2759794/> | "741636" | <http://nytimes.com> |
----------------------------------------------------------------------------------------------------------------------------
There's only one result now; it seems that the other result was in the default graph.
You can specify which graphs you want to query by using the graph
keyword this way. The details are described in 13.3 Querying the Dataset of the SPARQL 1.1 Recommendation.
By using the graph ?g { }
in the query, you're forcing the data to be in a named graph (i.e., you won't be getting triples from the default graph anymore). This seems to remove some of the results that you wanted, unfortunately. E.g., Applying this to you original query (not restricted to Amsterdam):
prefix oxprop: <http://ophileon.com/ox/property#>
prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>
prefix owl: <http://www.w3.org/2002/07/owl#>
prefix wgs84_pos: <http://www.w3.org/2003/01/geo/wgs84_pos#>
prefix gn: <http://www.geonames.org/ontology#>
select *
from <http://www.ophileon.com/ox/poi.rdf>
where
{
?poi rdfs:label ?poiname.
?poi owl:sameAs ?geonameuri.
SERVICE <http://factforge.net/sparql>{
graph ?g { ?geonameuri gn:population ?population. }
}
FILTER(langMatches(lang(?poiname), "EN")).
}
SPARQL results
------------------------------------------------------------------------------------------------------------------------------
| poi | poiname | geonameuri | population | g |
==============================================================================================================================
| <http://ophileon.com/ox/poi/3> | "Netherlands"@en | <http://sws.geonames.org/2750405/> | "16645000" | <http://nytimes.com> |
| <http://ophileon.com/ox/poi/1> | "Amsterdam"@en | <http://sws.geonames.org/2759794/> | "741636" | <http://nytimes.com> |
------------------------------------------------------------------------------------------------------------------------------
gives just two results; you no longer have a result for Wageningen. You can try asking for results with and without a graph, using
{ graph ?g { ?geonameuri gn:population ?population. } }
union
{ ?geonameuri gn:population ?population. }
SPARQL results
------------------------------------------------------------------------------------------------------------------------------
| poi | poiname | geonameuri | population | g |
==============================================================================================================================
| <http://ophileon.com/ox/poi/2> | "Wageningen"@en | <http://sws.geonames.org/2745088/> | "35433" | |
| <http://ophileon.com/ox/poi/3> | "Netherlands"@en | <http://sws.geonames.org/2750405/> | "16645000" | <http://nytimes.com> |
| <http://ophileon.com/ox/poi/3> | "Netherlands"@en | <http://sws.geonames.org/2750405/> | "16645000" | |
| <http://ophileon.com/ox/poi/1> | "Amsterdam"@en | <http://sws.geonames.org/2759794/> | "741636" | <http://nytimes.com> |
| <http://ophileon.com/ox/poi/1> | "Amsterdam"@en | <http://sws.geonames.org/2759794/> | "767457" | |
| <http://ophileon.com/ox/poi/1> | "Amsterdam"@en | <http://sws.geonames.org/2759794/> | "741636" | |
------------------------------------------------------------------------------------------------------------------------------
and now we see the data a bit more clearly. We can't say for sure, but it looks like the nytimes data is duplicated in the default graph, which is good in the case of Netherlands which might not have a value otherwise, but bad in the case of Amsterdam, where the default graph already has a value, and it differs from the one in the named graph.
The direct answer, then, is yes you can control which graphs are queried, but in the case it's not at all clear what data you'd want to use. You might be better off grouping by the values that expect to be the same for each location, and then combining the population results in some fashion (e.g., taking the maximum, or the minimum, or concatenating them, or something else. E.g., (note that we added a xsd:
prefix for casting to xsd:integer
, and that the ?population
values are strings, hence the need for casting to xsd:integer
in order to take the average):
prefix oxprop: <http://ophileon.com/ox/property#>
prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>
prefix owl: <http://www.w3.org/2002/07/owl#>
prefix wgs84_pos: <http://www.w3.org/2003/01/geo/wgs84_pos#>
prefix gn: <http://www.geonames.org/ontology#>
prefix xsd: <http://www.w3.org/2001/XMLSchema#>
select
?poi
?poiname
?geonameuri
(min(?population) as ?minPopulation)
(max(?population) as ?maxPopulation)
(group_concat(?population;separator=' ') as ?allPopulations)
(avg(xsd:integer(?population)) as ?avgPopulation)
(sample(?population) as ?somePopulation)
from <http://www.ophileon.com/ox/poi.rdf>
where
{
?poi rdfs:label ?poiname.
?poi owl:sameAs ?geonameuri.
SERVICE <http://factforge.net/sparql> {
?geonameuri gn:population ?population.
}
FILTER(langMatches(lang(?poiname), "EN")).
}
group by ?poi ?poiname ?geonameuri
SPARQL results
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| poi | poiname | geonameuri | minPopulation | maxPopulation | allPopulations | avgPopulation | somePopulation |
=============================================================================================================================================================================
| <http://ophileon.com/ox/poi/2> | "Wageningen"@en | <http://sws.geonames.org/2745088/> | "35433" | "35433" | "35433" | 35433.0 | "35433" |
| <http://ophileon.com/ox/poi/3> | "Netherlands"@en | <http://sws.geonames.org/2750405/> | "16645000" | "16645000" | "16645000" | 16645000.0 | "16645000" |
| <http://ophileon.com/ox/poi/1> | "Amsterdam"@en | <http://sws.geonames.org/2759794/> | "741636" | "767457" | "767457 741636" | 754546.5 | "767457" |
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
来源:https://stackoverflow.com/questions/19412208/limiting-graphs-to-be-used-by-factforge-sparql-endpoint