递归地将过滤器应用于连接的顶点 (SPARQL)

Applying a filter to connected vertices recursively (SPARQL)

这是另一个 regarding using SPAQRL for RDF to come up with a query that filters out all vertices that have any edges to other vertices that are not in a list of specified values, for which I received 的跟进问题。

这是我正在使用的图形的可视化表示,其中包含两种不同的 RDF 类型(:package:platform)的节点。在此图中,包(:Package_A:Package_B:Package_C:Package_D)具有到它们需要的每个平台的传出边,平台的值为 :Platform_1::Platform_2.

在此后续中,包现在也可以依赖于其他包,这在图表上使用从 :package 到另一个 :package:requires 边表示,当它对它有依赖性。

在上图中,Package_A需要Package_BPackage_C,而Package_BPackage_C需要Package_D

这是创建此图的数据:

INSERT DATA {
   :Package_A             rdf:type   :package .
   :Package_B             rdf:type   :package .
   :Package_C             rdf:type   :package .
   :Package_D             rdf:type   :package .

   :Platform_1            rdf:type   :platform .
   :Platform_2            rdf:type   :platform .

   :Package_A             :platform  :Platform_1 .
   :Package_B             :platform  :Platform_1 .
   :Package_C             :platform  :Platform_1 .
   :Package_D             :platform  :Platform_1 . 

   :Package_D             :platform  :Platform_2 .

   :Package_A             :requires  :Package_B .
   :Package_A             :requires  :Package_C .
   :Package_B             :requires  :Package_D .
   :Package_C             :requires  :Package_D .
}

我能够查询此图以过滤掉所有 :package 顶点,这些顶点与不在指定值列表中的其他顶点有任何边。 例如,对于这个指定的单例列表:[:Platform_1],以下查询会过滤掉 Package_D,因为它同时包含 Platform_1Platform_2 的边(Platform_2 不在指定的列表中)。 Package_APackage_BPackage_C 被返回,因为这些包 只有 具有通向 Platform_1.

的边
SELECT * {
    ?package a :package .
     FILTER NOT EXISTS {
         ?package :platform ?platform . 
         FILTER (?platform NOT IN(:Platform_1))
     }
}

我现在正在尝试扩展此查询,以便它也过滤掉 :requires 任何其他满足相同条件且具有到不在指定列表中的值。

意味着在列表 [:Platform_1] 的情况下,应过滤掉 所有 包,因为所有包在 [ 上至少具有可传递的 :requires =29=],它有一个到 Platform_2 的 :platform 边缘,它不在指定的列表中。

在列表 [:Platform_1, :Platform_2] 的情况下,应返回所有包顶点,因为所有包顶点只有连接到 Platform_1Platform_2 的边。

我尝试使用递归运算符 * 作为获取所有可传递 :requires 路径的方法,并对其应用上面的相同过滤器。但是,这在指定列表 [:Platform_1] 时不起作用,因为此查询的结果仍然包含 Package_APackage_BPackage_C:

SELECT * {
    ?package a :package .
     FILTER NOT EXISTS {
         ?package :requires* ?requires .
         ?package :platform ?platform . 
         FILTER (?platform NOT IN(:Platform_1))
     }
}

任何人都知道我如何构建一个查询来过滤掉所有顶点,这些顶点与不在指定值列表中的其他顶点有任何边,并且还过滤掉任何具有 :requires 的顶点通向满足相同条件的另一个顶点的边(直接或传递)?

一个很发人深省的问题。 在您的查询中,您想要过滤掉任何传递依赖于其他包的包,这些包具有已批准平台列表的平台 'outside'。

以下查询将起作用:

SELECT * {
    ?package a :package .
     FILTER NOT EXISTS {
         ?package :requires* ?requirement .
         ?requirement :platform ?platform .
         FILTER (?platform NOT IN(:Platform_1))
     }
}

与您的查询不同的是,具有平台的是需求,而不是包。 * 将处理没有要求的情况(即包 D),以及当我们查看包本身的平台时。

为简洁起见,当您对需求列表不感兴趣时​​,您可以这样表达上述查询:

SELECT * {
        ?package a :package .
         FILTER NOT EXISTS {
             ?package :requires*/:platform ?platform . #Notice the /.
             FILTER (?platform NOT IN(:Platform_1))
         }
    }