如何归还单一的foaf:名字?

时间:2013-06-16 00:41:20

标签: rdf sparql

我有以下DBpedia SPARQL,它显示了影响哲学家的哲学家。但是,当哲学家有多个foaf:name

时,它会返回重复项
SELECT ?name ?influencedName
  WHERE {
  ?philosopher a dbpedia-owl:Philosopher ;
    dbpedia-owl:influenced ?influenced ;
    foaf:name ?name .
  ?influenced  a dbpedia-owl:Philosopher ;
    foaf:name ?influencedName .
}

SPARQL results

如果?name?includedName有多个值,如何返回单个名称。我会很高兴第一个,或者最少数量的角色来选择保留。

这是柏拉图影响Bertrand Russell的另一个例子。我想这会返回一行,但我得到四行:

SELECT ?name ?influencedName
  WHERE {
  ?philosopher a dbpedia-owl:Philosopher ;
    dbpedia-owl:influenced ?influenced ;
    foaf:name ?name , "Plato"@en .
  ?influenced  a dbpedia-owl:Philosopher ;
    foaf:name ?influencedName, "Bertrand Arthur William Russell, 3rd Earl Russell"@en .
}

SPARQL results

2 个答案:

答案 0 :(得分:3)

查询

听起来你想要一个类似的查询:

SELECT ?philosopher ?pName ?influence (SAMPLE(?iName) as ?iName)
WHERE {
  # This subquery selects all the philosophers and
  # selects just one of their names . 
  {
    SELECT ?philosopher (SAMPLE(?pName) as ?pName) WHERE {
      ?philosopher a dbpedia-owl:Philosopher ;
                   foaf:name ?pName .
    }
    GROUP BY ?philosopher
  }

  # This main query selects the influence of the 
  # philosophers and select their names.  The GROUP
  # BY on the outer query puts all the
  # (?philosopher,?pName,?influence,?iName) tuples 
  # that have the same ?philosopher, ?pName, and 
  # influence together, and the (SAMPLE(?iName) as ?iName)
  # in the outer SELECT combines them all, choosing an 
  # arbitrary representative ?iName.
  ?influence dbpedia-owl:influenced ?philosopher ;
             a dbpedia-owl:Philosopher ;
             foaf:name ?iName .
}
GROUP BY ?philosopher ?pName ?influence

SPARQL results

如果您只对名称感兴趣而不关心选择实际资源,那么最外面的?philosopher中不需要?influenceSELECT,并且可以将其设为< / p>

SELECT ?pName (SAMPLE(?iName) as ?iName)
WHERE { …

SPARQL results

您还可能希望在结尾添加ORDER BY,以便更轻松地检查结果:

…
GROUP BY ?philosopher ?pName ?influence
ORDER BY ?pName

SPARQL results

对于柏拉图来说,最后的结果包括以下几行:

"Plato"@en  "Socrates"@en
"Plato"@en  "Parmenides"@en
"Plato"@en  "Zeno of Elea"@en
"Plato"@en  "Pythagoras"@en
"Plato"@en  "Gorgias"@en
"Plato"@en  "Protagoras"@en
"Plato"@en  "Heraclitus"@en

在我在这里写的查询中,我使用SAMPLE任意选择哲学家的foaf:name之一,但aggregate algebra中还有其他函数您可以用来选择一个值。如果您想按顺序使用“第一个”值,Min可能会对您感兴趣。

子查询,GROUP BY和SAMPLE,MIN等

这实际上与SPARQL规范的Section 12, Subqueries中的子查询的示例非常相似。在该示例中,以下查询用于选择Alice知道的人员,并且对于每个人,只选择其中一个人员名称:

PREFIX : <http://people.example/>
SELECT ?y ?minName
WHERE {
  :alice :knows ?y .
  {
    SELECT ?y (MIN(?name) AS ?minName)
    WHERE {
      ?y :name ?name .
    } GROUP BY ?y
  }
}

这不是很难适应哲学影响问题。哲学家的问题始于选择所有的哲学家及其名字,按实际的哲学家资源分组,并使用样本为每个哲学家挑选一个代表性名称。外部查询也是如此,但不是选择哲学家,而是选择影响每个哲学家的实体。将结果分组并选择影响力的代表名称。

答案 1 :(得分:1)

我已经确定了如何为哲学家选择唯一的名称,请参阅下面的sparql,它为每个哲学家返回一个名称。

但是,我没有看到为什么要将这个结合到更大的查询中,该查询为哲学家和受影响的哲学家返回一个名称而不为每个哲学家运行一次这将是一个庞大而笨拙的查询。我的感觉是,如果我分别运行哲学名称和查询影响并在代码中查找名称而不是sparql,我的代码将更具可读性。也许我错过了一些sparql功能,这将使这很容易。请建议

以下是我如何获得唯一名称的说明:

从foaf获取哲学家的所有名称:names和dbprop:names 过滤以仅包含至少包含一个拉丁字母字符的名称(A-Z) 找到最短名称的长度 选择所有最短的名称

中的最小值
PREFIX dbpedia: <http://dbpedia.org/>
PREFIX dbpedia-owl: <http://dbpedia.org/ontology/>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX dbpprop: <http://dbpedia.org/property/>

SELECT ?philosopher (min(?name) as ?minName)
WHERE {{
   ?philosopher foaf:name ?name        .
  } UNION {
   ?philosopher dbpprop:name ?name     .
  }
  FILTER( strlen(?name) = ?minLength )   .  # get the shortest names
  FILTER( REGEX( str(?name) , "[A-Z]" )) .  # exlude names with no latin charachters
  {
    SELECT ?philosopher (min(strlen(?name)) as ?minLength)
    WHERE {{
      ?philosopher a  dbpedia-owl:Philosopher ;
         foaf:name ?name .
    } UNION {
      ?philosopher a  dbpedia-owl:Philosopher ;
         dbpprop:name ?name .
    }
    FILTER( REGEX( str(?name) , "[A-Z]" )) .
    }
    GROUP BY ?philosopher
  }
}
GROUP BY ?philosopher
ORDER BY ?philosopher