在运行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
Run Code Online (Sandbox Code Playgroud)
它超时了.什么更有效(以避免超时)在我的代码中删除和处理结果?
1-聚合(group_concat)
2-过滤器:在我的代码中对其进行后处理
3-子查询:删除一些子查询(Optional vs Union)并在另一个查询中执行
优化问题很难,特别是当端点可以施加不同的限制时.也就是说,至少有一些东西可以简化这个查询.
{?film a dbpedia-owl:Film } UNION {?film a dbpedia-owl:TelevisionShow } UNION {?film a dbpedia-owl:Cartoon } UNION {?film a dbpedia-owl:TelevisionSeason } .
Run Code Online (Sandbox Code Playgroud)
应该是:
values ?filmType { dbpedia-owl:Film
dbpedia-owl:Television
dbpedia-owl:Cartoon
dbpedia-owl:TelevisionSeason }
?film a ?filmType
Run Code Online (Sandbox Code Playgroud)
这将处理所有固定类型.下一部分
filter(regex(?filmType,"(?:TelevisionSeason|Cartoon|Film|TelevisionShow)"))
Run Code Online (Sandbox Code Playgroud)
似乎旨在找到任何类型包含其中一个字符串的东西.这可能会遍历所有个体及其所有类型,然后在所有类型上运行正则表达式.啊.更好的方法是找到名称与该东西匹配的本体类,然后检索这些类的个体.
(请注意,除此之外,卡通可能会提到非电影事物;例如,报纸上的政治漫画.)
也就是说,一个更好的解决方案可能是稍微浏览类层次结构,看看是否有一些你感兴趣的东西的常见超类.如果某个东西是子类的成员,那么它也是超类的成员,所以你可以保存一些查询方式.
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 } .
Run Code Online (Sandbox Code Playgroud)
除了以下情况之外,你可以做些什么来清理它们:
也就是说,如果您确实想要获取超过属性的值,只需在属性路径中使用交替构造即可.例如,第一个可选块变为:
OPTIONAL { {?film dbpedia-owl:starring|dbpprop:starring ?actors }
Run Code Online (Sandbox Code Playgroud)
摆脱了联盟,使你的查询更简单.
OPTIONAL { ?film owl:sameAs ?dblink .
Filter (strstarts( str(?dblink), 'http://dbpedia.org/resource/'))}
Run Code Online (Sandbox Code Playgroud)
虽然owl:sameAs具有传递性和反身性,但这应该不错,所以你应该让链接朝着两个方向前进.此外(这并不重要),您可以通过使用str获取前缀使您的查询更易于维护.从而:
prefix dbpedia: <http://dbpedia.org/resource/>
optional { ?film (owl:sameAs|^owl:sameAs)* ?dblink .
filter (strstarts( str(?dblink), str(:dbpedia) ) }
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
您正在使用多个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
Run Code Online (Sandbox Code Playgroud)
我知道Virtuoso可以在没有显式组的情况下接受查询,但在SPARQL中是必需的.事实上,我回答了最近的答案.semanticweb.com问题,当已经触及这一点的范围内错误时使用变量.在sparql.org的验证器中检查您的查询是个好主意.