本文介绍了SPARQL可选查询的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在下面的代码中,我有Turtle格式的RDF

    @prefix ab: <http://learningsparql.com/ns/addressbook#> .
    @prefix d: <http://learningsparql.com/ns/data#> .
    d:i0432 ab:firstName "Richard" .
    d:i0432 ab:lastName "Mutt" .
    d:i0432 ab:homeTel "(229) 276-5135" .
    d:i0432 ab:nick "Dick" .
    d:i0432 ab:email "[email protected]" .
    d:i9771 ab:firstName "Cindy" .
    d:i9771 ab:lastName "Marshall" .
    d:i9771 ab:homeTel "(245) 646-5488" .
    d:i9771 ab:email "[email protected]" .
    d:i8301 ab:firstName "Craig" .
    d:i8301 ab:lastName "Ellis" .
    d:i8301 ab:workTel "(245) 315-5486" .
    d:i8301 ab:email "[email protected]" .
    d:i8301 ab:email "[email protected]" .

,查询为

    PREFIX ab: <http://learningsparql.com/ns/addressbook#>
    SELECT ?first ?last
    WHERE
    {
        ?s ab:lastName ?last .
        OPTIONAL {?s ab:nick ?first. }.
        OPTIONAL {?s ab:firstName ?first .}.
    }

结果为

    ------------------------
    | first   | last       |
    ========================
    | "Craig" | "Ellis"    |
    | "Cindy" | "Marshall" |
    | "Dick"  | "Mutt"     |
    ------------------------

但如果我将查询更改为

    PREFIX ab: <http://learningsparql.com/ns/addressbook#>
    SELECT ?first ?last
    WHERE
    {
        OPTIONAL {?s ab:nick ?first. }.
        OPTIONAL {?s ab:firstName ?first .}.
        ?s ab:lastName ?last .
    }

结果为

    -------------------
    | first  | last   |
    ===================
    | "Dick" | "Mutt" |
    -------------------

有没有人能解释一下造成这种差异的原因?我以为SPARQL查询中的句点与"AND"运算符相同。

推荐答案

这里排序很重要

SPARQL查询的语义是通过SPARQL代数表示的,这里的两个查询产生了非常不同的代数。我使用Apache Jena项目提供的SPARQL Query Validator(免责声明-我是该项目的提交者)来生成代数。

您的第一个查询生成以下代数:

(base <http://example/base/>
  (prefix ((ab: <http://learningsparql.com/ns/addressbook#>))
    (project (?first ?last)
      (leftjoin
        (leftjoin
          (bgp (triple ?s ab:lastName ?last))
          (bgp (triple ?s ab:nick ?first)))
        (bgp (triple ?s ab:firstName ?first))))))

第二个查询生成以下代数:

(base <http://example/base/>
  (prefix ((ab: <http://learningsparql.com/ns/addressbook#>))
    (project (?first ?last)
      (join
        (leftjoin
          (leftjoin
            (table unit)
            (bgp (triple ?s ab:nick ?first)))
          (bgp (triple ?s ab:firstName ?first)))
        (bgp (triple ?s ab:lastName ?last))))))

如您所见,查询中的三元组模式以不同的顺序出现,运算符也不同。重要的是,您的第二个查询有一个join,它只保留双方的兼容解决方案,而第一个查询只使用leftjoin,如果没有兼容的解决方案,它会按原样保留LHS解决方案。

因此,在第一个查询中,您首先查找带有ab:lastName的内容,然后可以选择添加ab:nickab:firstName(如果存在),从而返回数据中的所有人员。

在第二个查询中,您首先使用ab:nick查找内容,然后可选地使用ab:firstName添加内容,然后要求所有内容都具有ab:lastName。因此,您只能获取返回姓氏的人员。

否,它只是终止一个三元组模式,并且可以选择性地跟在其他子句之后(但不是必须这样做),它不是"AND"运算符。

除非leftjoinminus子句的存在暗示了替代连接运算符(例如leftjoinminus),否则相邻的基本图形模式将被连接

编辑-什么是table unit

table unit是与SPARQL查询中的空图模式相对应的特殊运算符。

例如SELECT * WHERE { }将生成代数(table unit)

它生成一个空行,在SPARQL的语义中,这意味着它可以连接到任何东西,并返回另一个东西,因此本质上它就像一个连接标识。在许多情况下,SPARQL引擎可以简化代数以删除table unit,因为在大多数情况下,它对查询的语义没有影响。

在您的第一个查询中,从技术上讲,table unitjoin运算符之间有另一个join,但是在正常联接的情况下,table unit的存在将不起作用(因为它是联接标识),因此它可以并被简化。

但是,对于OPTIONAL,SPARQL规范要求生成的代数是子句内部的东西与前面的子句的左连接。在第二个查询中,第一个OPTIONAL之前没有前面的子句(从技术上讲,那里有一个隐式的空图模式),因此生成的第一个leftjoin在其左侧有table unit。与正常的join不同,table unit在这种情况下必须保留,因为leftjoin的语义表示,如果RHS中没有兼容的解决方案,则保留来自LHS的结果。

我们可以用一个更简单的查询来说明这一点:

SELECT *
WHERE
{
  OPTIONAL { ?s a ?type }
}

生成代数:

(base <http://example/base/>
  (leftjoin
    (table unit)
    (bgp (triple ?s <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> ?type))))

这篇关于SPARQL可选查询的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-06 07:01