SPARQL-запрос работает в Fuseki, но не в Jena TDB

Мои данные организованы в несколько графиков. График, в котором сохраняется тройка, имеет значение. Структура данных сложна, но ее можно упростить следующим образом:

Мой магазин содержит торты, где есть иерархия различных типов тортов, все подклассы <cake>

<http://example.com/a1> a <http://example.com/applecake>
<http://example.com/a2> a <http://example.com/rainbowcake>
...

В зависимости от того, как они создаются пользователем в пользовательском интерфейсе, они оказываются на другом графике. Например, если пользователь "печет" торт, он отправляется в <http://example.com/homemade> график, если они "покупают" один, он идет в <http://example.com/shopbought> граф.

Когда я получаю свои пирожные в магазине, я хочу знать для каждого пирога, самодельный или купленный в магазине. Для этого нет свойства, я хочу получить информацию исключительно на основе графика, в котором хранится тройка.

Я пробовал различные способы достижения этого, но ни один из них не работает в Jena TDB. Проблема в том, что все торты возвращаются как "купленные в магазине". Однако все запросы работают в Fuseki (на точном наборе данных sae), и мне было интересно, является ли это ошибкой TDB или есть другой способ. Вот упрощенные запросы (без вариантов):

Версия 1:

SELECT DISTINCT  *
FROM <http://example.com/homemade>
FROM <http://example.com/shopbought>
FROM NAMED <http://example.com/homemade>
FROM NAMED <http://example.com/shopbought>
WHERE {
    ?cake rdf:type ?caketype .
    ?caketype rdfs:subClassOf* <cake>
      {
          GRAPH <http://example.com/homemade> { ?cake rdf:type ?typeHomemade }
      } UNION {
          GRAPH <http://example.com/shopbought> { ?cake rdf:type ?typeShopbought }
      }
    BIND(str(if(bound(?typeHomemade), true, false)) AS ?homemade)
}

Версия 2:

SELECT DISTINCT  *
    FROM <http://example.com/homemade>
    FROM <http://example.com/shopbought>
    FROM NAMED <http://example.com/homemade>
    FROM NAMED <http://example.com/shopbought>
    WHERE {
        ?cake rdf:type ?caketype .
        ?caketype rdfs:subClassOf* <cake>
        GRAPH ?g {
          ?cake rdf:type ?caketype .
        }
        BIND(STR(IF(?g=<http://example.com/homemade>, true, false)) AS ?homemade)
    }

Есть идеи, почему это работает в Fuseki, но не в TDB?

Изменить: я начинаю думать, что это как-то связано с ключевым словом GRAPH. Вот несколько более простых запросов (которые работают в Fuseki и tdbquery) и результаты, которые я получаю с помощью Jena API:

SELECT * WHERE { GRAPH <http://example.com/homemade> { ?s ?p ?o }}

0 результатов

SELECT * WHERE { GRAPH ?g { ?s ?p ?o }}

0 результатов

SELECT * FROM <http://example.com/homemade> WHERE { ?s ?p ?o }

х результаты

SELECT * FROM <http://example.com/homemade> WHERE { GRAPH <http://example.com/homemade> { ?s ?p ?o }}

0 результатов

SELECT * FROM NAMED <http://example.com/homemade> WHERE { GRAPH <http://example.com/homemade> { ?s ?p ?o }}

0 результатов

1 ответ

Решение

Итак, мое решение на самом деле связано с тем, как я выполнил запрос. Моя первоначальная идея состояла в том, чтобы предварительно отфильтровать набор данных так, чтобы запрос выполнялся только для соответствующих графиков (набор данных содержит много графиков, и они могут быть довольно большими, что сделает запрос "все" медленным). Это может быть сделано либо путем добавления их в SPARQL, либо непосредственно в Jena (хотя это не будет работать для других тройных магазинов). Однако объединение обоих способов "быть на безопасной стороне" не работает.

Этот запрос выполняется для всего набора данных и работает как положено:

Query query = QueryFactory.create("SELECT * WHERE { GRAPH ?g { ?s ?p ?o } }", Syntax.syntaxARQ);
QueryExecution qexec = QueryExecutionFactory.create(query, dataset);
ResultSet result = qexec.execSelect();

Тот же запрос может быть выполнен только для определенного графа, где не имеет значения, какой граф, он не дает никаких результатов:

//run only on one graph
Model target = dataset.getNamedModel("http://example.com/homemade");
//OR run on the union of all graphs
Model target = dataset.getNamedModel("urn:x-arq:UnionGraph");
//OR run on a union of specific graphs
Model target = ModelFactory.createUnion(dataset.getNamedModel("http://example.com/shopbought"), dataset.getNamedModel("http://example.com/homemade"), ...);
[...]
QueryExecution qexec = QueryExecutionFactory.create(query, target);
[...]

Мой обходной путь заключался в том, чтобы теперь всегда запрашивать весь набор данных (который отлично поддерживает ключевое слово SPARQL GRAPH) и для каждого запроса всегда указывать графики, на которых он должен выполняться, чтобы избежать необходимости запрашивать весь набор данных. Не уверен, что это ожидаемое поведение для Jena API

Другие вопросы по тегам