在运行SPARQL查询和您编写的代码之间需要权衡清理结果
复杂查询: Pros
:获取干净/高效的结果,减少清理代码 Cons:
超时错误,处理时间长。
我知道有人不能概括它,但想比较梳理子查询(UNION,...),过滤器和聚合,看看在超时的情况下哪一个是更昂贵的操作。
例如,我从日语SPARQL端点运行此查询(我删除了它的一部分)。
SELECT ?film ?dblink ?filmType (group_concat(?actors ; separator = "|") AS ?actorset) (group_concat(?country ; separator = "|") AS ?countryset) (group_concat(?releaseDate ; separator = "|") AS ?releasedateset) (group_concat(?language ; separator = "|") AS ?languageset) (group_concat(?genre ; separator = "|") AS ?genreset) ?numberOfEpisodes ?numberOfSeasons
WHERE {
{?film a dbpedia-owl:Film } UNION {?film a dbpedia-owl:TelevisionShow } UNION {?film a dbpedia-owl:Cartoon } UNION {?film a dbpedia-owl:TelevisionSeason } .
{?film a ?filmType } .Filter(regex(?filmType,"(?:TelevisionSeason|Cartoon|Film|TelevisionShow)")) .
OPTIONAL { {?film dbpedia-owl:starring ?actors} UNION {?film dbpprop:starring ?actors} }. OPTIONAL { ?film dbpedia-owl:country ?country }. OPTIONAL { {?film dbpprop:genre ?genre} UNION { ?film dbpedia-owl:genre ?genre } }. OPTIONAL { {?film dbpprop:language ?language} UNION {?film dbpedia-owl:language ?language} }. OPTIONAL { ?film dbpedia-owl:wikiPageID ?wikiPageID } .
OPTIONAL {?film owl:sameAs ?dblink . Filter (strstarts( str(?dblink), 'http://dbpedia.org/resource/'))}
} LIMIT 5
它超时了。什么更有效(以避免超时)在我的代码中删除和处理结果?
1-聚合(group_concat)
2-过滤器:在我的代码中对其进行后期处理
3-子查询:删除一些子查询(Optional vs Union)并在另一个查询中执行它们
答案 0 :(得分:5)
优化问题很难,特别是当端点可以施加不同的限制时。也就是说,至少有一些东西可以简化这个查询。
{?film a dbpedia-owl:Film } UNION {?film a dbpedia-owl:TelevisionShow } UNION {?film a dbpedia-owl:Cartoon } UNION {?film a dbpedia-owl:TelevisionSeason } .
应该是:
values ?filmType { dbpedia-owl:Film
dbpedia-owl:Television
dbpedia-owl:Cartoon
dbpedia-owl:TelevisionSeason }
?film a ?filmType
这将处理所有固定类型。下一部分
filter(regex(?filmType,"(?:TelevisionSeason|Cartoon|Film|TelevisionShow)"))
似乎旨在查找具有包含其中一个字符串的类型的任何内容。这可能会遍历所有个体及其所有类型,然后在所有类型上运行正则表达式。啊。更好的方法是找到名称与该东西匹配的本体类,然后检索这些类的个体。
(请注意,除此之外,卡通可能会提到非电影事物;例如报纸上的政治漫画。)
也就是说,一个更好的解决方案可能是稍微浏览一下类层次结构,看看是否有一些你感兴趣的东西的常见超类。如果某个东西是子类的成员,那么它也是超类的成员,所以你可以通过这种方式保存一些查询。
OPTIONAL { {?film dbpedia-owl:starring ?actors} UNION
{?film dbpprop:starring ?actors} } .
OPTIONAL { ?film dbpedia-owl:country ?country } .
OPTIONAL { {?film dbpprop:genre ?genre } UNION
{?film dbpedia-owl:genre ?genre } }.
OPTIONAL { {?film dbpprop:language ?language} UNION
{?film dbpedia-owl:language ?language} }.
OPTIONAL { ?film dbpedia-owl:wikiPageID ?wikiPageID } .
除了:
之外,你可以做些什么来清理它们也就是说,如果你想要获得超过属性的值,只需在属性路径中使用交替构造即可。例如,第一个可选块变为:
OPTIONAL { {?film dbpedia-owl:starring|dbpprop:starring ?actors }
摆脱了联盟,使你的查询更简单。
OPTIONAL { ?film owl:sameAs ?dblink .
Filter (strstarts( str(?dblink), 'http://dbpedia.org/resource/'))}
这并不坏,虽然owl:sameAs是传递性和反身性的,所以你应该让链接朝着两个方向前进。此外(这并不重要),您可以使用str
获取前缀,使您的查询更易于维护。因此:
prefix dbpedia: <http://dbpedia.org/resource/>
optional { ?film (owl:sameAs|^owl:sameAs)* ?dblink .
filter (strstarts( str(?dblink), str(:dbpedia) ) }
SELECT
?film ?dblink ?filmType
(group_concat(?actors ; separator = "|") AS ?actorset)
(group_concat(?country ; separator = "|") AS ?countryset)
(group_concat(?releaseDate ; separator = "|") AS ?releasedateset)
(group_concat(?language ; separator = "|") AS ?languageset)
(group_concat(?genre ; separator = "|") AS ?genreset)
?numberOfEpisodes ?numberOfSeasons
WHERE { … }
LIMIT 5
您正在使用多个group_concat
聚合。这可能本身并不是一个问题,因为它只是遍历每个组并构建一个字符串。这与您拥有的结果数量(在群组之前)呈线性关系,所以它不应该太昂贵。但是,选择组和非分组变量时,不是合法的。如果您要在没有聚合的情况下选择五个变量,则需要通过以下方式明确使用组:
SELECT
?film ?dblink ?filmType
(group_concat(?actors ; separator = "|") AS ?actorset)
(group_concat(?country ; separator = "|") AS ?countryset)
(group_concat(?releaseDate ; separator = "|") AS ?releasedateset)
(group_concat(?language ; separator = "|") AS ?languageset)
(group_concat(?genre ; separator = "|") AS ?genreset)
?numberOfEpisodes ?numberOfSeasons
WHERE { }
GROUP BY ?film ?dblink ?filmType ?numberOfEpisodes ?numberOfSeasons
LIMIT 5
我知道Virtuoso可以在没有显式组的情况下接受查询,但在SPARQL中是。事实上,我回答了最近的答案.semanticweb.com问题,Variable used when already in-scope error触及了这一点。在sparql.org's validator中查看您的查询是个不错的主意。