选择依赖树上的连接顶点并按深度对其进行排序 (SPARQL)

问题描述

我将 SPARQL 用于 RDF,但在提出一个查询时遇到了问题,该查询将允许我选择树上的一组顶点,并将所有连接(直接和传递)顶点与所选顶点返回,并且按照它们在依赖树上存在的深度顺序(最深的顶点在前)。

这是我正在使用的图形(树)的可视化表示,其中包含 RDF 类型 :dependency 的节点。在这棵树中,依赖项具有到它们所需的每个依赖项的传出边,这在图上使用 :requires 边表示。

enter image description here

这是创建此图的数据:

INSERT DATA {
   :A             rdf:type   :dependency .
   :B             rdf:type   :dependency .
   :C             rdf:type   :dependency .
   :D             rdf:type   :dependency .
   :E             rdf:type   :dependency .
   :F             rdf:type   :dependency .
   :G             rdf:type   :dependency .
   :H             rdf:type   :dependency .
   :I             rdf:type   :dependency .
   :J             rdf:type   :dependency .
   :K             rdf:type   :dependency .

   :A             :requires  :B .
   :A             :requires  :C .
   :A             :requires  :I .
   :B             :requires  :J .
   :B             :requires  :E .
   :C             :requires  :D .
   :E             :requires  :F .
   :E             :requires  :G .
   :D             :requires  :G . 
   :H             :requires  :I .     
   :H             :requires  :K .
}

我想形成一个查询,允许我选择一组依赖项,并按照首先返回最低的 :required 依赖项的顺序返回该选择的所有依赖项,这样如果“依赖项X" :requires "Dependency Y",那么Dependency X必须在结果集中afterDependency Y。

本质上,我想问图表:

“给我这组顶点需要的所有顶点,并按顺序返回它们,以便最低级别的依赖项在结果集上优先”

例如,在上图中指定这个选择的情况下:[B,H]

一个有效的结果集是: [G,F,E,J,B,I,K,H]

(因为GFB的最低依赖,其次是EJ等等...)

以下结果集也将被视为有效: [J,G,H]

因为在 JFG 之前或之后返回 H 并不重要,因为它不依赖于它们(重要的是它在 B 之前返回,因为 B 需要所有这些)

到目前为止,我已经尝试了对选择 [B,H] 的这个查询,它能够返回 BH 的所有必需的依赖项,但它们没有按顺序返回最低依赖优先级。

SELECT ?requires {
    ?dependency a :dependency .
    FILTER (?dependency IN (:B,:H))
    ?dependency :requires+ ?requires .
}

错误的顺序返回结果集: [E,K]

有人知道我如何构造一个查询,该查询基本上执行顶点的深度优先搜索排序吗?

解决方法

感谢@UninformedUser 分享的 this answer,我可以获得与我要查找的内容足够接近的结果集。基本上我们可以使用属性路径来确定所有 :requires 位于一组指定顶点之下的边,同时保留一个计数器来返回每个边的深度:

如果我们想确定这个选择 [B,H] 的顺序,那么我们可以使用这个查询,它是上面答案中查询的稍微修改版本,以允许选择开始顶点从顶部选择所有路径:

select ?begin ?midI ?midJ (count(?counter) as ?position) ?end where {
  ?begin a :dependency .
  FILTER (?begin IN (:B,:H))
  ?begin :requires* ?counter .
  ?counter :requires* ?midI .

  ?midI :requires ?midJ .

  ?midJ :requires* ?end .
  FILTER NOT EXISTS { ?end :requires [] }
}
group by ?begin ?end ?midI ?midJ 
order by DESC(?position) ?begin ?end 

这将返回以下结果集:

----------------------------------------
| begin | midI | midJ | position | end |
========================================
| :B    | :E   | :F   | 2        | :F  |
| :B    | :E   | :G   | 2        | :G  |
| :B    | :B   | :E   | 1        | :F  |
| :B    | :B   | :E   | 1        | :G  |
| :B    | :B   | :J   | 1        | :J  |
| :H    | :H   | :I   | 1        | :I  |
| :H    | :H   | :K   | 1        | :K  |
----------------------------------------

这足以让我在客户端使用代码执行剩余的排序,其中对于 begin 列中的每个唯一值,收集 midJ 的所有值(从顶部开始到底部),直到用完相同 begin 值的所有行,然后最后将该值包含在 begin 列中。 对上述结果集执行此操作时,我们得到了有效答案: [F,G,E,B,J,I,K,H]

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...