RDF перечисляет предметы с их объектами в одну строку

У меня есть файл RDF, и мне нужно извлечь некоторую информацию из него и записать его в файл. Я понял, как это в принципе работает, но я застрял с этим:

String queryString = "select ?person ?children where { ?person ?hasChildren ?children}";
TupleQuery tupleQuery = conn.prepareTupleQuery(QueryLanguage.SPARQL, queryString);
TupleQueryResult result = tupleQuery.evaluate();     
while (result.hasNext()) {
    BindingSet bindingSet = result.next();
    Value p1 = bindingSet.getValue("person");
    Value p2 = bindingSet.getValue("child");
    println(p1 + " has children " + p2 +"");
}
result.close();

Вывод, который я получаю, выглядит так:

http://example.org/people/person1 has children http://example.org/people/child1
http://example.org/people/person1 has children http://example.org/people/child2

Я не вижу, как перечислить всех людей с их объектами в этом формате:

person1 has children child1 and child2

Как это может быть сделано?

1 ответ

Решение

Вы можете найти этот ответ, который описывает SPARQL group_concatПолезно:

В SPARQL, когда у вас есть набор результатов решений для запросов, вы можете group на одну или несколько переменных, объединяя решения, которые имеют эти общие переменные. Например, рассмотрим данные

@prefix : <http://example.org/people/>.

:person1 :hasChild :child1, :child2, :child3 .
:person2 :hasChild :child4, :child5 .
:person3 :hasChild :child6 .

Если вы выполните следующий запрос на нем

prefix : <http://example.org/people/>

select ?person ?child where { 
  ?person :hasChild ?child .
}

Вы получаете результаты, подобные этим:

$ arq --data data.n3 --query query.sparql
----------------------
| person   | child   |
======================
| :person3 | :child6 |
| :person2 | :child5 |
| :person2 | :child4 |
| :person1 | :child3 |
| :person1 | :child2 |
| :person1 | :child1 |
----------------------

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

$ arq --data data.n3 --query query.sparql
----------------------------------------
| person   | child                     |
========================================
| :person3 | :child6                   |
| :person2 | :child4, :child5          |
| :person1 | :child1, :child2, :child3 |
----------------------------------------

и это именно то, что group_by Позвольте нам сделать. Такой запрос:

prefix : <http://example.org/people/>

select ?person (group_concat(?child;separator=' and ') as ?children) where { 
  ?person :hasChild ?child .
}
group by ?person

производит (обратите внимание, что переменная в результате ?childrenне ?childпотому что мы использовали group_concat(...) as ?children создать новую переменную ?children):

$ arq --data data.n3 --query query.sparql
---------------------------------------------------------------------------------------------------------------------------
| person   | children                                                                                                     |
===========================================================================================================================
| :person3 | "http://example.org/people/child6"                                                                           |
| :person1 | "http://example.org/people/child3 and http://example.org/people/child2 and http://example.org/people/child1" |
| :person2 | "http://example.org/people/child5 and http://example.org/people/child4"                                      |
---------------------------------------------------------------------------------------------------------------------------

Если вы используете такой запрос и будете перебирать результаты, печатая их как есть, вы получите результат, который хотите. Если вы хотите лишить ведущих http://example.org/people/ Вдали от людей и детей вам понадобится немного больше обработки строк. Например, используя STRAFTER для удаления http://example.org/people/ Префикс, вы можете использовать запрос как этот:

prefix : <http://example.org/people/>

select
 (strafter(str(?personX),"http://example.org/people/") as ?person)
 (group_concat(strafter(str(?child),"http://example.org/people/");separator=' and ') as ?children)
where { 
  ?personX :hasChild ?child .
}
group by ?personX

чтобы получить результаты, такие как:

$ arq --data data.n3 --query query.sparql
----------------------------------------------
| person    | children                       |
==============================================
| "person3" | "child6"                       |
| "person2" | "child5 and child4"            |
| "person1" | "child3 and child2 and child1" |
----------------------------------------------

который, когда вы будете печатать, даст вам такие результаты, как

person3 has children child6
person2 has children child5 and child4
person1 has children child3 and child2 and child1
Другие вопросы по тегам