【问题标题】:SPARQL to get all parents of all nodesSPARQL 获取所有节点的所有父节点
【发布时间】:2015-07-19 00:53:08
【问题描述】:

我一直在使用这篇文章来获取单个 RDF 节点的父节点或血统:SPARQL query to get all parent of a node

这在我的 virtuoso 服务器上运行良好。抱歉,找不到包含具有类似结构的数据的公共端点。

prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>
prefix bto: <http://purl.obolibrary.org/obo/>
select (group_concat(distinct ?midlab ; separator = "|") AS ?lineage)
where
{ 
  bto:BTO_0000207 rdfs:subClassOf* ?mid .
  ?mid rdfs:subClassOf* ?class .
  ?mid rdfs:label ?midlab .
}
group by ?lineage
order by (count(?mid) as ?ordercount)

给予

+---------------------------------------------------------+
|                         lineage                         |
+---------------------------------------------------------+
| bone|cartilage|connective tissue|tibia|tibial cartilage |
+---------------------------------------------------------+

然后我想知道是否可以通过将选择更改为

来获取所有节点的血统
select ?s (group_concat(distinct ?midlab ; separator = "|") AS ?lineage)

和where语句中的第一行

?s rdfs:subClassOf* ?mid .

那些比我有更多 SPARQL 经验的人可能不会对查询超时感到惊讶。

这是一个合理的方法吗?我在语法上做错了吗?

我怀疑 distinct 关键字或组子句是瓶颈,因为这只需要一两秒钟:

prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#>
prefix bto: <http://purl.obolibrary.org/obo/>
select ?s ?midlab
where
{ 
  ?s rdfs:subClassOf* ?mid .
  ?mid rdfs:subClassOf* ?class .
  ?mid rdfs:label ?midlab .
  ?s <http://www.geneontology.org/formats/oboInOwl#hasOBONamespace> "BrendaTissueOBO"^^<http://www.w3.org/2001/XMLSchema#string> .
}

【问题讨论】:

    标签: rdf sparql virtuoso


    【解决方案1】:

    您的第一个查询不合法。您可以查看sparql.org's query validator。虽然您可以按 count(?mid) 排序,但不能将值绑定到变量并在同一子句中按它排序。那会给你:

    select (group_concat(distinct ?midlab ; separator = "|") AS ?lineage)
    where
    { 
      bto:BTO_0000207 rdfs:subClassOf* ?mid .
      ?mid rdfs:subClassOf* ?class .
      ?mid rdfs:label ?midlab .
    }
    group by ?lineage
    order by count(?mid)
    

    现在,这是合法,但它的意义不大。 group_concat 要求您有一些组,并且您将对每个组中的值进行串联。在没有 group by 子句的情况下,您会得到一个隐式组,因此没有 group bygroup_concat 是可以的。但是你有一个 group by ?lineage 并没有多大意义,因为 ?lineage 每个组已经只有一个值(因为它已经是总计的)。最好按 ?s 分组,如下所示。这似乎更正确,并且可能不会超时:

    select ?s (group_concat(distinct ?midlab ; separator = "|") AS ?lineage)
    where
    { 
      ?s rdfs:subClassOf* ?mid .
      ?mid rdfs:subClassOf* ?class .
      ?mid rdfs:label ?midlab .
    }
    group by ?s
    order by count(?mid)
    

    【讨论】:

    • 这看起来很有希望。我添加了一个 from 子句并将 order by 更改为 "(count(?mid) as ?midcount)" 并得到了合理的结果。
    • @MarkMiller order by (... as ...) 不合法。 Virtuoso 可能会接受它(它接受许多非标准语法),但它不是合法的 SPARQL。如果您需要针对另一个端点运行查询,它很可能不起作用。你可以select (count(?mid) as ?midcount) { ... } order by ?midcount,你可以select ... { ... } order by count(?mid),但你不能select ... { ... } order by (count(?mid) as ?midcount)。变量绑定形式(... as ...)order by ... 中是不合法的。 (不过,在group by合法的。)
    • 非常感谢您的反馈,并为没有更仔细地学习而道歉。我也在评估 MarkLogic 时使用 Jena 广告,因此最佳实践对我来说很重要。 “按计数排序(?mid)”引发“Virtuoso 37000 错误 SP030:SPARQL 编译器,第 12 行:'(' 在 '?mid' 之前的语法错误” 只需将其括在括号中而不使用 AS 就可以工作并通过验证器。
    • @MarkMiller 是的,Virtuoso 的怪癖总是让人感到沮丧。一些大型可公开访问的端点(例如,DBpedia)使用端点,所以很多人从这里开始,但最终学习了一些坏习惯。 :) Virtuoso 不接受正确语法很少见(is接受的不正确语法是更常见),所以 order by 问题有点令人沮丧。不过,我很高兴您找到了解决方法(带括号)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-03-11
    • 2019-07-14
    • 1970-01-01
    • 1970-01-01
    • 2012-10-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多