SPARQL查询从DBpedia检索国家/地区人口

Yag*_*güe 2 sparql dbpedia

我开发了以下SPARQL查询,以获取其人口来自DBpedia的国家/地区列表.我使用union条款来确定哪些资源是当前国家,因为不同国家之间的信息不一致,例如国家代码有不同的标准,有些甚至没有.

现在我遇到的问题是,有些国家拥有dbpprop:populationEstimate财产,但其他国家拥有财产,而dbpprop:populationCensus我不知道如何让两者都绑定?population.因为现在我只得到估计人口,我想这是因为有两个OPTIONAL条款匹配?population没有意义,但我无法接近解决方案.

例如印度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)
}
Run Code Online (Sandbox Code Playgroud)

谢谢大家的帮助:)

Jos*_*lor 5

首先,我将使用DBpedia SPARQL端点中定义的前缀,以便我们可以复制和粘贴查询.我认为唯一的区别是dbo现在会dbpedia-owl.其次,您正在使用许多原始数据属性,但如果可以,您应该尝试使用本体中的属性,如本答案中所述.这不一定会影响您在此处获得的结果,但如果您使用本体属性,通常会获得更清晰的数据.

修改您的查询

FILTER NOT EXISTS用于删除已结束的国家/地区

让我们首先清理查询,然后倾向于获取各种人口属性的问题.删除具有结束日期的国家/地区可以更简单地完成.代替

OPTIONAL {?country dbpprop:yearEnd ?yearEnd}
FILTER (!bound(?yearEnd))
Run Code Online (Sandbox Code Playgroud)

你可以使用它FILTER NOT EXISTS来更直接:

FILTER NOT EXISTS { ?country dbpprop:yearEnd ?yearEnd }
Run Code Online (Sandbox Code Playgroud)

为了尝试使用DBpedia本体中的属性dbpedia-owl:dissolutionYear而不是Raw Infobox数据属性,您可能需要考虑使用而不是dbpprop:yearEnd,给予:

FILTER NOT EXISTS { ?country dbpedia-owl:dissoluationYear ?yearEnd }
Run Code Online (Sandbox Code Playgroud)

简化语言过滤

rdfs:label期望值是文字是合理的,并且lang函数要求其参数是文字,因此您不需要绑定str(?enName)?name; 只需绑定?name三重模式,然后检查它的语言(你正确使用它)就足够了langMatches.也就是说,而不是

?country rdfs:label ?enName .   
FILTER (langMatches(lang(?enName), "en")) 
BIND (str(?enName) AS ?name)
Run Code Online (Sandbox Code Playgroud)

你可以使用

?country rdfs:label ?name .   
FILTER (langMatches(lang(?name), "en"))
Run Code Online (Sandbox Code Playgroud)

这意味着您获得的名称将具有语言标记.如果你真的只想要普通的字符串,你可以像以前一样BIND,或者as在select中做一个表达式,例如:

SELECT DISTINCT (str(?name) as ?noLangName) ?population
Run Code Online (Sandbox Code Playgroud)

检查人口是否受约束并且是一个数字

我不认为过滤xsd:integer(?population)也会对你有很大帮助.这种表示法不是一个类型谓词,而是一个转换函数,因此?population被转换为整数,我认为过滤器总是会让值通过,除非是0失败的情况.你仍然想知道一个国家是否有人口0,对吧?但是,您只希望拥有人口的国家,因此您可以使用bound以下内容进行过滤:

FILTER(bound(?population))
Run Code Online (Sandbox Code Playgroud)

但是,由于这里的属性是原始信息框属性,因此数据中存在一些噪声,因此我们最终会得到类似的值

"Denmark"@en "- Density 57,695"@en
"Denmark"@en "- Faroe Islands"@en
Run Code Online (Sandbox Code Playgroud)

哪些都没用.一个更好的过滤器只会检查该值是一个数字(这将隐式要求它的绑定),并且有一个函数isNumeric只是为了这个目的,所以我们使用:

FILTER (isNumeric(?population))
Run Code Online (Sandbox Code Playgroud)

使用VALUES简化类似的UNION模式

您可以使用清理UNION模式VALUES.UNION您可以定义一个?hasCode只有值dbpprop:iso3166code等的变量,而不是几个几乎相同的模式.即,而不是:

{ ?country dbpprop:iso3166code ?code . }
UNION
{ ?country dbpprop:iso31661Alpha ?code . }
UNION
{ ?country dbpprop:countryCode ?code . }
UNION
{ ?country a yago:MemberStatesOfTheUnitedNations . }
Run Code Online (Sandbox Code Playgroud)

您可以使用:

values ?hasCode { dbpprop:iso3166code dbpprop:iso31661Alpha dbpprop:countryCode }
{ ?country ?hasCode ?code . }
UNION
{ ?country a yago:MemberStatesOfTheUnitedNations . }
Run Code Online (Sandbox Code Playgroud)

您可以使用?population检索执行类似的操作:

OPTIONAL {?country dbpprop:populationEstimate ?population}
OPTIONAL {?country dbpprop:populationCensus ?population}
Run Code Online (Sandbox Code Playgroud)

可以变成:

values ?hasPopulation { dbpprop:populationEstimate dbpprop:populationCensus }
OPTIONAL { ?country ?hasPopulation ?population }
Run Code Online (Sandbox Code Playgroud)

最后的结果

重写的查询现在是:

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 . }
}
Run Code Online (Sandbox Code Playgroud)

SPARQL结果

印度现在出现在人口结果中:

"India"@en 1210193422
Run Code Online (Sandbox Code Playgroud)