1

我对 SPARQL 很陌生,并且对它现有的多种语法标准感到困惑。我正在努力使用以下查询从 DBpedia 获取唯一数据:

SELECT DISTINCT ?Museum, ?name, ?abstract, ?thumbnail, ?latitude,
   ?longitude, ?photoCollection, ?website, ?homepage, ?wikilink
WHERE { 
  ?Museum a dbpedia-owl:Museum ; 
          dbpprop:name ?name ; 
          dbpedia-owl:abstract ?abstract ; 
          dbpedia-owl:thumbnail ?thumbnail ; 
          geo:lat ?latitude ;  
          geo:long ?longitude ; 
          dbpprop:hasPhotoCollection ?photoCollection ;
          dbpprop:website ?website ; 
          foaf:homepage ?homepage ; 
          foaf:isPrimaryTopicOf ?wikilink .
  FILTER(langMatches(lang(?abstract),"EN")) 
  FILTER (langMatches(lang(?name),"EN"))
}
LIMIT 20

SPARQL 结果

任何人都可以看到, 和 的条目Geffrye_MuseumInstitute_for_Museum_Research结果中重复,因为Institute_for_Museum_Research它的名称有两个不同的值,并且 Geffrye_Museum有两个经度值。在这两种重复的情况下,我都希望丢弃第二个值;即,必须忽略Geffrye_Museum经度值,而必须忽略名称值。-0.0762194Institute_for_Museum_Research"Institut für Museumsforschung"@en

请注意,我已经在为我想要的字段应用过滤,这只是我想在查询级别本身处理的 DBpedia 中的大量数据。那么当同一列有多个值时,如何让 DBpedia 只返回第一个值?

4

1 回答 1

6

我们先来看一个案例。在 Geffrye 的情况下,会出现重复的结果,因为数据中存在多个经度,如以下查询所示:

SELECT ?museum ?latitude ?longitude
WHERE { 
  VALUES ?museum { dbpedia:Geffrye_Museum }
  ?museum a dbpedia-owl:Museum ; 
          geo:lat ?latitude ;  
          geo:long ?longitude .
}
GROUP BY ?museum ?latitude ?longitude

SPARQL 结果

产生

museum                                     latitude longitude
http://dbpedia.org/resource/Geffrye_Museum 51.5317  -0.07663
http://dbpedia.org/resource/Geffrye_Museum 51.5317  -0.0762194

幸运的是,这很容易补救。正如在这个问题中所讨论的,您可以按其特征值对结果进行分组,然后对这些值进行采样、最小化、最大化等,以获得您想要的结果。例如,如果您想要最大的经度值,您可以MAX(?longtude) as ?longitude在 SELECT 中使用,如下面的查询,它产生一个值。

SELECT ?museum ?latitude (MAX(?longitude) as ?longitude)
WHERE { 
  VALUES ?museum { dbpedia:Geffrye_Museum }
  ?museum a dbpedia-owl:Museum ; 
          geo:lat ?latitude ;  
          geo:long ?longitude .
}
GROUP BY ?museum ?latitude

SPARQL 结果

当然,它需要一些知识来分组?latitude和最大化?longitude?museum将其他值分组并使用聚合投影来提取其他值可能是一个更好的主意,如下所示:

SELECT ?museum (MAX(?latitude) as ?latitude) (MAX(?longitude) as ?longitude)
WHERE { 
  VALUES ?museum { dbpedia:Geffrye_Museum }
  ?museum a dbpedia-owl:Museum ; 
          geo:lat ?latitude ;  
          geo:long ?longitude .
}
GROUP BY ?museum

SPARQL 结果

对所有变量采用这种方法会产生如下结果:

SELECT DISTINCT ?Museum
  (SAMPLE(?name) as ?name)
  (SAMPLE(?abstract) as ?abstract)
  (SAMPLE(?thumbnail) as ?thumbnail)
  (MAX(?latitude) as ?latitude)
  (MAX(?longitude) as ?longitude)
  (SAMPLE(?photoCollection) as ?photoCollection)
  (SAMPLE(?website) as ?website)
  (SAMPLE(?homepage) as ?homepage)
  (SAMPLE(?wikilink) as ?wikilink)
WHERE { 
  ?Museum a dbpedia-owl:Museum ; 
          dbpprop:name ?name ; 
          dbpedia-owl:abstract ?abstract ; 
          dbpedia-owl:thumbnail ?thumbnail ; 
          geo:lat ?latitude ;  
          geo:long ?longitude ; 
          dbpprop:hasPhotoCollection ?photoCollection ;
          dbpprop:website ?website ; 
          foaf:homepage ?homepage ; 
          foaf:isPrimaryTopicOf ?wikilink .
  FILTER(langMatches(lang(?abstract),"EN")) 
  FILTER (langMatches(lang(?name),"EN"))
}
GROUP BY ?Museum
LIMIT 20

SPARQL 结果

必须对所有变量使用聚合投影似乎有点尴尬,但它会起作用。但是,您也可以先在子查询中进行聚合,这将清理变量投影,但代价是子查询。(子查询不一定对查询产生负面影响;实际上可能正好相反。不过,查询本身有点难以阅读。)

SELECT * WHERE { 
  # Select museums and a single latitude and longitude for them.
  {
    SELECT ?Museum (MAX(?longitude) as ?longitude) (MAX(?latitude) as ?latitude) WHERE {
      ?Museum a dbpedia-owl:Museum ;
              geo:lat ?latitude ;
              geo:long ?longitude .
    }
    GROUP BY ?Museum
  }
  # Get the rest of the properties of the museum.
  ?Museum dbpprop:name ?name ;
          dbpedia-owl:abstract ?abstract ; 
          dbpedia-owl:thumbnail ?thumbnail ; 
          dbpprop:hasPhotoCollection ?photoCollection ;
          dbpprop:website ?website ; 
          foaf:homepage ?homepage ; 
          foaf:isPrimaryTopicOf ?wikilink .
  FILTER(langMatches(lang(?abstract),"EN")) 
  FILTER (langMatches(lang(?name),"EN"))
}
GROUP BY ?Museum
LIMIT 20

SPARQL 结果

最后,由于您需要对名称和地理坐标进行规范化,您的最终查询将类似于以下内容。在您的问题中,您只说要保留“第一个结果”,但没有对结果施加特定的顺序,因此没有唯一的“第一个结果”。有了手头的数据,您可以使用(MIN(?name) as ?name)并获得您想要的博物馆研究所名称,但如果您有特定的限制,您需要弄清楚如何使其更具体。

SELECT * WHERE { 
  # Select museums and a single latitude, longitude, and name for them.
  {
    SELECT ?Museum 
           (MIN(?name) as ?name)
           (MAX(?longitude) as ?longitude)
           (MAX(?latitude) as ?latitude)
    WHERE {
      ?Museum a dbpedia-owl:Museum ;
              dbpprop:name ?name ;
              geo:lat ?latitude ;
              geo:long ?longitude .
      FILTER (langMatches(lang(?name),"EN"))
    }
    GROUP BY ?Museum
  }
  # Get the rest of the properties of the museum.
  ?Museum dbpprop:name ?name ;
          dbpedia-owl:abstract ?abstract ; 
          dbpedia-owl:thumbnail ?thumbnail ; 
          dbpprop:hasPhotoCollection ?photoCollection ;
          dbpprop:website ?website ; 
          foaf:homepage ?homepage ; 
          foaf:isPrimaryTopicOf ?wikilink .
  FILTER(langMatches(lang(?abstract),"EN")) 
}
LIMIT 20

SPARQL 结果

于 2013-06-18T19:56:15.270 回答