首页 > 解决方案 > 如何优化我的递归 SPARQL 查询?

问题描述

我正在尝试使用递归 SPARQL 查询从 Wikidata 中提取建筑物,但我不断收到查询超时。有没有办法绕过这个?

这是我当前的查询,选择所有具有 Freebase ID 或 Google Knowledge Graph ID 以及荷兰标签的建筑物:

SELECT DISTINCT ?building ?buildingLabel
WHERE {
  ?building p:P2671|p:P646 ?id;
            p:P31/ps:P31/wdt:P279* wd:Q41176;
            rdfs:label ?buildingLabel .
  FILTER(LANG(?buildingLabel) = 'nl') .
  FILTER (?building != ?buildingLabel) .
}

我已经尝试手动查看几层深度,但由于某种原因,我没有得到三层或更多层深度的结果,即使它们确实存在。我已经尝试过使用:

SELECT ?building
WHERE {
 ?building p:P31/ps:P31/wdt:P279 [p:P31/ps:P31/wdt:P279 [p:P31/ps:P31/wdt:P279 wd:Q41176]].
}

并使用

SELECT ?building
WHERE {
 ?parent2 p:P31/ps:P31/wdt:P279 wd:Q41176.
 ?parent1 p:P31/ps:P31/wdt:P279 ?parent2.
 ?building p:P31/ps:P31/wdt:P279 ?parent1.
}

Wikidata 上有大约 224 万座建筑物和大约 1800 万个具有 Freebase ID 或 Google Knowledge Graph ID 的实体。我查看了本指南,但不太清楚如何将其应用于我的查询。我也阅读了这个问题的答案,但不幸的是,使用多个查询对我来说并不是一个真正的选择。

标签: query-optimizationsparqlwikidata

解决方案


如果您打算使用“递归”属性路径来查找类型为建筑物的事物以及作为建筑物子类的类型,那么您使用的第一个查询wdt:P279*是正确的,而稍后重复完整模式的尝试p:P31/ps:P31/wdt:P279将不匹配任何数据。

通过稍微简化第一个查询,我能够让它运行(在 39 秒内返回 96,297 个结果):

SELECT DISTINCT ?building ?buildingLabel
WHERE {
  ?building p:P2671|p:P646 ?id;
            wdt:P31/wdt:P279* wd:Q41176 .
  ?building rdfs:label ?buildingLabel .
  FILTER(LANGMATCHES(LANG(?buildingLabel), "nl"))
}

两个显着的变化:

  • p:P31/ps:P31替换为wdt:P31,从查询中删除一个连接。
  • 第二个FILTER是不必要的,因为?building(a URI) 和?buildingLabel(a string) 必然是不相等的

推荐阅读