【问题标题】:Finding the relative position of elements in a list using SPARQL使用 SPARQL 查找列表中元素的相对位置
【发布时间】:2018-04-25 05:01:03
【问题描述】:

我正在尝试根据主题在有序列表中的相对位置返回主题。

一个主题可以与多个对象相关联(通过一个谓词),并且所有对象都在一个有序列表中。给定此列表中的参考对象,我想按照对象与参考对象的相对距离的顺序返回主题。

:a : :x     
:b : :v
:b : :z
:c : :v
:c : :y

:ls :list (:v :w :x :y :z)

以x作为我们在列表中的起始对象,下面的代码返回

:a :x :0
:c :y :1
:b :v :2
:b :z :2
:c :v :2

我不希望返回所有位置,而是只希望返回与主体的最小对象“距离”相关的对象(这可能意味着每个主体最多两个对象 - 在列表的上方和下方)。所以我想回来

:a :x :0
:c :y :1
:b :v :2
:b :z :2

到目前为止的代码... (在Find lists containing ALL values in a set?Is it possible to get the position of an element in an RDF Collection in SPARQL? 的大力帮助下)

SELECT ?s ?p (abs(?refPos-?pos) as ?dif) 
WHERE {
      :ls :list/rdf:rest*/rdf:first ?o .
      ?s : ?o .
      {
      SELECT ?o (count(?mid) as ?pos) ?refPos 
      WHERE {
            [] :list/rdf:rest* ?mid . ?mid rdf:rest* ?node .
            ?node rdf:first ?o .
            {
            SELECT ?o (count(?mid2) as ?refPos)
            WHERE {
                  [] :list/rdf:rest* ?mid2 . ?mid2 rdf:rest* ?node2 .
                  ?node2 rdf:first :x .
                  }
            }
            }
            GROUP BY ?o
      }
      }
      GROUP BY ?s ?o
      ORDER BY ?dif

我一直试图通过按 ?s 分组来获得最小 ?dif(差异/距离),但是因为我必须将这个(类似于 ?dif = ?minDif)应用到之前的 ?s ?o 分组我不知道如何在这两个分组之间来回切换。

感谢您提供的任何帮助

【问题讨论】:

  • 您确定这是 SPARQL 的正确用例吗?听起来像 Cypher 或 Gremlin 这样的图遍历引擎在这里会更好地工作。
  • 感谢@AKSW 的这些建议。我想将列表提供的层次结构合并到我的 SPARQL 查询中,但如果我继续使用这种方法,我将研究图遍历引擎。

标签: sparql


【解决方案1】:

您需要的只是另一种解决方案 Joshua Taylor 的回答:thisthis

下面我使用的是 Jena 函数,但我希望这个想法很清楚。

查询 1

PREFIX list: <http://jena.hpl.hp.com/ARQ/list#>
SELECT ?s ?el ?dif {
    ?s : ?el .
    :ls :list/list:index (?pos ?el) .
    :ls :list/list:index (?ref :x) .
    BIND (ABS(?pos -?ref) AS ?dif) 
    {
    SELECT ?s (MIN (?dif_) AS ?dif) WHERE {
        ?s : ?el_ .
        :ls :list/list:index (?pos_ ?el_) .
        :ls :list/list:index (?ref_ :x) .
        BIND (ABS(?pos_ - ?ref_) AS ?dif_)
        } GROUP by ?s
    }
}

查询 2

PREFIX list: <http://jena.apache.org/ARQ/list#>    
SELECT ?s ?el ?dif {
    ?s : ?el .
    :ls :list/list:index (?pos ?el) .
    :ls :list/list:index (?ref :x) .
    BIND (ABS(?pos -?ref) AS ?dif) 
    FILTER NOT EXISTS {
        ?s : ?el_ .
        :ls :list/list:index (?pos_ ?el_) .
        BIND (ABS(?pos_ - ?ref) AS ?dif_) .
        FILTER(?dif_ < ?dif)                                           
    }
}

更新

查询1可以这样改写:

PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>

SELECT ?s ?el ?dif {
  ?s : ?el 
  { select (count(*) as ?pos) ?el {[] :list/rdf:rest*/rdf:rest*/rdf:first ?el} group by ?el }
  { select (count(*) as ?ref)     {[] :list/rdf:rest*/rdf:rest*/rdf:first :x} } 
  BIND (ABS(?pos - ?ref) AS ?dif) 
  {
  SELECT ?s (MIN(?dif_) AS ?diff) {
    ?s : ?el_ 
    { select (count(*) as ?pos_) ?el_ {[] :list/rdf:rest*/rdf:rest*/rdf:first ?el_} group by ?el_ }
    { select (count(*) as ?ref_)      {[] :list/rdf:rest*/rdf:rest*/rdf:first :x} } 
    BIND (ABS(?pos_ - ?ref_) AS ?dif_)
    } GROUP by ?s
  }
  FILTER (?dif = ?diff)
}

备注

  • 如您所见,这不是 SPARQL 的设计目的。例如,Blazegraph 支持 Gremlin...
  • 可能这不是 RDF 的设计目的。或者尝试其他建模方法:您真的需要 RDF 列表吗?
  • 我没有在 Virtuoso 中测试过上述查询。

【讨论】:

  • 感谢@Stanislav Kralin,我一直在玩直接的 SPARQL(因此是详细的位置查询)。
  • 再次感谢@Stanislav Kralin。我只是想使用列表提供的层次结构探索一些数据(同时更加熟悉 SPARQL)。如果它看起来很有希望并且我继续使用这种方法,我会检查 Gremlin。另外,我只是在 RDFLib 中运行这些查询,它们都工作正常。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-03-15
  • 1970-01-01
  • 2016-06-28
  • 2021-12-04
  • 1970-01-01
相关资源
最近更新 更多