我开发了以下SPARQL查询,以获取其人口来自DBpedia的国家/地区列表。我使用union条款来确定哪些资源是当前国家,因为不同国家之间的信息不一致,例如国家代码有不同的标准,其中一些甚至没有。
现在我遇到的问题是,有些国家/地区有dbpprop:populationEstimate
属性但其他国家/地区有dbpprop:populationCensus
但我不知道如何让它们绑定?population
。因为现在我只得到估计人口,我想这是因为有两个OPTIONAL
条款匹配?population
没有意义,但我无法接近解决方案。< / p>
例如India有dbpprop:populationCensus
,但它没有出现在结果中。
PREFIX dbpprop: <http://dbpedia.org/property/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX yago:<http://dbpedia.org/class/yago/>
PREFIX dbo: <http://dbpedia.org/ontology/>
PREFIX category: <http://dbpedia.org/resource/Category:>
PREFIX xsd:<http://www.w3.org/2001/XMLSchema#>
SELECT DISTINCT ?name ?population
WHERE {
?country a dbo:Country .
?country rdfs:label ?enName .
OPTIONAL {?country dbpprop:populationEstimate ?population}
OPTIONAL {?country dbpprop:populationCensus ?population}
OPTIONAL {?country dbpprop:yearEnd ?yearEnd}
{ ?country dbpprop:iso3166code ?code . }
UNION
{ ?country dbpprop:iso31661Alpha ?code . }
UNION
{ ?country dbpprop:countryCode ?code . }
UNION
{ ?country a yago:MemberStatesOfTheUnitedNations . }
FILTER (langMatches(lang(?enName), "en"))
FILTER (!bound(?yearEnd))
FILTER (xsd:integer(?population))
BIND (str(?enName) AS ?name)
}
感谢大家的帮助:)
答案 0 :(得分:5)
首先,我将使用DBpedia SPARQL endpoint中定义的前缀,以便我们可以复制和粘贴查询。我认为唯一的区别是dbo
现在将是dbpedia-owl
。其次,您正在使用许多原始数据属性,但如果可以,您应该尝试使用本体中的属性,如this answer中所述。这不一定会影响您在此处获得的结果,但如果您使用本体属性,通常会获得更清晰的数据。
让我们首先清理查询,然后倾向于获取各种人口属性的问题。删除具有结束日期的国家/地区可以更简单地完成。而不是
OPTIONAL {?country dbpprop:yearEnd ?yearEnd}
FILTER (!bound(?yearEnd))
您可以使用FILTER NOT EXISTS
使其更加直接:
FILTER NOT EXISTS { ?country dbpprop:yearEnd ?yearEnd }
尝试使用DBpedia本体中的属性而不是Raw Infobox数据属性时,您可能需要考虑使用dbpedia-owl:dissolutionYear
而不是dbpprop:yearEnd
,并给出:
FILTER NOT EXISTS { ?country dbpedia-owl:dissoluationYear ?yearEnd }
期望rdfs:label
值为文字是合理的,lang
函数要求其参数为文字,因此您不需要将str(?enName)
绑定到{{ 1}};只需在三重模式中绑定?name
,然后检查其语言(使用?name
正确执行)就足够了。也就是说,而不是
langMatches
你可以使用
?country rdfs:label ?enName .
FILTER (langMatches(lang(?enName), "en"))
BIND (str(?enName) AS ?name)
这确实意味着您获得的名称将具有语言标记。如果你真的只想要普通字符串,你可以像以前一样BIND,或者在select中做一个?country rdfs:label ?name .
FILTER (langMatches(lang(?name), "en"))
表达式,例如
as
我认为对SELECT DISTINCT (str(?name) as ?noLangName) ?population
的过滤也不会对你有很大帮助。该表示法不是类型谓词,而是一个转换函数,因此xsd:integer(?population)
被转换为整数,我认为过滤器将始终通过值,除了?population
的情况,哪会失败。你仍然想知道一个国家的人口是否0
,对吗?但是,您只希望拥有人口的国家/地区,因此您可以使用bound
过滤:
0
但是,由于此处的属性是原始信息框属性,因此数据中存在一些噪音,因此我们最终会得到像
这样的值FILTER(bound(?population))
没用。一个更好的过滤器只会检查该值是一个数字(这将隐式要求它被绑定),并且有一个函数isNumeric
就是为了这个目的,所以我们使用:
"Denmark"@en "- Density 57,695"@en
"Denmark"@en "- Faroe Islands"@en
您可以使用VALUES
清除FILTER (isNumeric(?population))
模式。您可以定义一个只有UNION
等值的变量UNION
,而不是?hasCode
几个几乎相同的模式。即,而不是:
dbpprop:iso3166code
你可以使用:
{ ?country dbpprop:iso3166code ?code . }
UNION
{ ?country dbpprop:iso31661Alpha ?code . }
UNION
{ ?country dbpprop:countryCode ?code . }
UNION
{ ?country a yago:MemberStatesOfTheUnitedNations . }
您可以使用values ?hasCode { dbpprop:iso3166code dbpprop:iso31661Alpha dbpprop:countryCode }
{ ?country ?hasCode ?code . }
UNION
{ ?country a yago:MemberStatesOfTheUnitedNations . }
检索执行类似操作:
?population
可以成为:
OPTIONAL {?country dbpprop:populationEstimate ?population}
OPTIONAL {?country dbpprop:populationCensus ?population}
现在重写的查询:
values ?hasPopulation { dbpprop:populationEstimate dbpprop:populationCensus }
OPTIONAL { ?country ?hasPopulation ?population }
印度现在出现在人口结果中:
SELECT DISTINCT ?name ?population
WHERE {
?country a dbpedia-owl:Country .
?country rdfs:label ?name .
FILTER (langMatches(lang(?name), "en"))
values ?hasPopulation { dbpprop:populationEstimate dbpprop:populationCensus }
OPTIONAL { ?country ?hasPopulation ?population }
FILTER (isNumeric(?population))
FILTER NOT EXISTS { ?country dbpedia-owl:dissolutionYear ?yearEnd }
values ?hasCode { dbpprop:iso3166code dbpprop:iso31661Alpha dbpprop:countryCode }
{ ?country ?hasCode ?code . }
UNION
{ ?country a yago:MemberStatesOfTheUnitedNations . }
}
答案 1 :(得分:3)
我想我已经知道如何解决这个问题。
对于可选子句,请使用单独的变量
OPTIONAL {?country dbpprop:populationEstimate ?populationEstimate}
OPTIONAL {?country dbpprop:populationCensus ?populationCensus}
OPTIONAL {?country dbpprop:yearEnd ?yearEnd}
然后,将其中一个绑定到?population
BIND(IF(bound(?populationEstimate), ?populationEstimate, ?populationCensus) as ?population)
最后,检查过滤器表达式中的绑定变量
FILTER (xsd:integer(?population))
查询的其余部分保持不变。我已经针对DBpedia SPARQL端点进行了测试,乍一看,它似乎产生了正确的结果。
如果这是正确的,请告诉我。
PREFIX dbpprop: <http://dbpedia.org/property/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
PREFIX yago:<http://dbpedia.org/class/yago/>
PREFIX dbo: <http://dbpedia.org/ontology/>
PREFIX category: <http://dbpedia.org/resource/Category:>
PREFIX xsd:<http://www.w3.org/2001/XMLSchema#>
SELECT DISTINCT ?name ?population
WHERE {
?country a dbo:Country .
?country rdfs:label ?enName .
OPTIONAL {?country dbpprop:populationEstimate ?populationEstimate}
OPTIONAL {?country dbpprop:populationCensus ?populationCensus}
OPTIONAL {?country dbpprop:yearEnd ?yearEnd}
BIND(IF(bound(?populationEstimate), ?populationEstimate, ?populationCensus) as ?population)
FILTER (langMatches(lang(?enName), "en"))
FILTER (!bound(?yearEnd))
FILTER (xsd:integer(?population))
{ ?country dbpprop:iso3166code ?code . }
UNION
{ ?country dbpprop:iso31661Alpha ?code . }
UNION
{ ?country dbpprop:countryCode ?code . }
UNION
{ ?country a yago:MemberStatesOfTheUnitedNations . }
BIND (str(?enName) AS ?name)
}