SPARQL:将多个谓词值组合到标签数组中

时间:2019-05-17 19:04:24

标签: sparql wikidata

现在我有一个查询,该查询返回特定实体的各种属性的列表:

SELECT ?propLabel ?val WHERE {

  BIND(wd:Q122426 as ?entity)
  {
    BIND(?entity AS ?valUrl)
    BIND("n/a" AS ?propUrl)
    BIND("name"@en AS ?propLabel)
    ?entity rdfs:label ?val.
    FILTER((LANG(?val)) = "en")

# instance of
  } UNION {
    ?entity wdt:P31 ?valUrl .
    BIND("instance of"@en AS ?propLabel)

    # filter  isIRI(?valUrl) 
    ?valUrl rdfs:label ?valLabel 
    FILTER (LANG(?valLabel) = "en") 
    BIND(CONCAT(?valLabel) AS ?val)

# occupation
  } UNION {
    ?entity wdt:P106 ?val.
    BIND("occupation"@en AS ?propLabel)

# position held
  } UNION {
    ?entity wdt:P39 ?val.
    BIND("position"@en AS ?propLabel)

# ... and more ...

  }
}

这很好用,但是它返回实体代码(Qxxxxx)而不是文本标签。所以我可以这样更改它:

# occupation
  } UNION {
    ?entity wdt:P106 ?valUrl.
    BIND("occupation"@en AS ?propLabel)

    ?valUrl rdfs:label ?valLabel 
    FILTER (LANG(?valLabel) = "en") 
    BIND(CONCAT(?valLabel) AS ?val)

那很好用。

但是我的问题是

如何将多个谓词的值“折叠”为字符串?即谓词P106,P119,Px,Py等获得:

| ?property   | ?valueLabel |
|-------------+-------------|
| tags  | politician, Giza East Field, something else, something else |
| name        | Henutsen    |

有没有比UNION构造每个谓词更有效的方法来构造查询?例如,仅提供谓词P31, P106, P39等的列表

1 个答案:

答案 0 :(得分:1)

这是一个用紧凑的UNION子句代替VALUES并使用label service(由AKSW表示感谢)的版本:

SELECT ?entity ?property ?valueLabel {
  VALUES ?entity { wd:Q122426 }
  VALUES (?p ?property) {
    (wdt:P31    "instance of"@en)
    (rdfs:label "name"@en)
    (wdt:P106   "occupation"@en)
    (wdt:P39    "position"@en)
  }
  ?entity ?p ?value
  FILTER (!isLiteral(?value) || lang(?value) = "" || langmatches(lang(?value), "en"))
  SERVICE wikibase:label { bd:serviceParam wikibase:language "en" }
}

结果:

| ?property   | ?valueLabel |
|-------------+-------------|
| instance of | human       |
| occupation  | politician  |
| name        | Henutsen    |

理论上也可以将多行折叠为单行,并以逗号分隔的列表作为值,并且看起来像这样:

SELECT ?entity
  (group_concat(?property; separator=", ") AS ?properties)
  (group_concat(?valueLabel; separator=", ") AS ?values)
WHERE {
  ...
}
GROUP BY ?entity

,原始查询插入...。这个想法是使用GROUP BY来按实体对结果进行分组(这里并不是绝对必要的,因为我们毕竟只有一个实体,但是如果您想向查询中添加更多实体),然后使用group_concat将每个实体的所有值合并为一个值。

不幸的是,由于某种原因,这不起作用; ?properties看起来不错,但?values为空。它可能与“魔术”标签服务有关,也许与聚合不兼容。

更新:这是一个将名称和“标签”作为单独的行返回的版本,如更新后的问题:

SELECT ?property ?valueLabel {
  {
    SELECT
      ("tags" AS ?property)
      (group_concat(?valueLabel; separator=", ") AS ?valueLabel)
    WHERE {
      VALUES ?p { wdt:P31 wdt:P106 wdt:P119 wdt:P39 }
      wd:Q122426 ?p ?value
      SERVICE wikibase:label { bd:serviceParam wikibase:language "en" }
    }
  } UNION {
    BIND ("name"@en AS ?property)
    wd:Q122426 rdfs:label ?valueLabel
    FILTER langMatches(lang(?valueLabel), "en")
  }
}

结果:

| ?property | ?valueLabel                        |
|-----------+------------------------------------|
| tags      | human, politician, Giza East Field |
| name      | Henutsen                           |

关于此查询,有些事情有些奇怪。请注意,标签服务为?valueLabel分配了一个值,但随后在内部子查询的SELECT子句中重新分配了一个不同的值。 SPARQL通常不允许这种重新分配,但实际上需要才能使查询正常工作。标签服务似乎有点奇怪。