SPARQL: объединить несколько значений предикатов в массив меток - PullRequest
2 голосов
/ 17 мая 2019

Прямо сейчас у меня есть запрос, который возвращает список различных свойств для конкретной сущности:

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 Ответ

1 голос
/ 21 мая 2019

Вот версия, которая заменяет UNION на компактное предложение VALUES и использование службы label (любезно предоставлено 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, но здесь на самом деле требуется , чтобы запрос работал. Это похоже на причуду со службой меток.

...