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

SPARQL:将多个谓词值组合到标签数组中,sparql,wikidata,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") # insta

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

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)
SELECT ?entity
  (group_concat(?property; separator=", ") AS ?properties)
  (group_concat(?valueLabel; separator=", ") AS ?values)
WHERE {
  ...
}
GROUP BY ?entity
这很好

但我的问题是 如何将多个谓词的值“折叠”为字符串?i、 e.对于谓词P106、P119、Px、Py等,获取:

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

是否有一种更有效的方法来构造查询,而不是
UNION
ing每个谓词?例如,只提供谓词列表
P31、P106、P39
etc

这里有一个版本,它用一个紧凑的
VALUES
子句替换
UNION
,并使用(由AKSW在评论中提供):

结果:

| ?property   | ?valueLabel |
|-------------+-------------|
| instance of | human       |
| occupation  | politician  |
| name        | Henutsen    |
理论上也可以将多行折叠为一行,并使用逗号分隔的列表作为值,如下所示:

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

    ?valUrl rdfs:label ?valLabel 
    FILTER (LANG(?valLabel) = "en") 
    BIND(CONCAT(?valLabel) AS ?val)
SELECT ?entity
  (group_concat(?property; separator=", ") AS ?properties)
  (group_concat(?valueLabel; separator=", ") AS ?values)
WHERE {
  ...
}
GROUP BY ?entity
将原始查询插入到
。我们的想法是使用
groupby
按实体对结果进行分组(这里没有严格的必要,因为我们只有一个实体,但如果您想向查询中添加更多实体),然后
GROUP_concat
将每个实体的所有值合并为一个值

不幸的是,出于某种原因,这不起作用<代码>属性看起来很好,但值为空。它可能与“magic”标签服务有关,可能与聚合不兼容

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

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中通常不允许这种重新分配,但在这里,它实际上是使查询工作所必需的。这似乎是标签服务的一个怪癖。

我不理解您查询中的
联合
的目的。您应该为每个可能缺少的属性使用
可选的
。对于值的“数组”,必须使用
group\u concat
作为聚合函数,并使用
group by
实体。注意,结果不是一个正确的数组,而是一个由所有连接值组成的字符串,并将给定的分隔符作为连接字符串。SparQl中没有这样的数组数据结构顺便说一下,您也可以在查询中获取属性标签,不需要手动绑定它们。谢谢。您可以编写建议的改进查询作为答案吗?我还在学习SPARQL。下面是你的一个更简洁的查询:
selectdistinct?propLabel(COALESCE(str(?valLabel),?val)as?value),其中{VALUES(?prop?propLabel){(rdfs:label“name”@en)(wdt:P106“occulation”@en)(wdt:P39“position”@en)}wd:Q122426?prop?val#如果它是一个文本并且有一个语言标记,那么使用英语的一个过滤器(!isLiteral(?val)| | | lang(?val)=“langmatches(lang(?val),“en”)|获取虹膜可选的标签{val rdfs:label?valLabel过滤器(langmatches(lang(?valLabel),“en”)}
使用Wikidata magic label服务:
选择distinct?property?valLabel,其中{VALUES(?prop?property){(rdfs:label“name”@en)(wdt:P106“occulation”@en)(wdt:P39“position”@en)}wd:Q122426?prop?val过滤器(!isLiteral(?val)| lang(?val)=“langmatches”(lang(?val),“en”))服务wikibase:label{bd:serviceParam wikibase:语言“en”。}
太棒了,谢谢!我编辑了我的问题,以便更清楚地说明分组请求。我了解了
group\u concat
的工作原理,只是有些细节不清楚。我正在WD查询服务中尝试这一点,但得到了一个空的标签字段-嗯,八天前我写答案时它起作用了。现在不起作用了。正如我在中所说的在响应的两部分中,标签服务与聚合交互的方式有些奇怪。可以尝试重写查询以不使用标签服务,但我将把这项工作留给其他人。非常感谢您的帮助!