Добавление возраста (целочисленных литералов) в тройки Jena RDF и выполнение запросов к ним с помощью SPARQL

#java #oracle #rdf #sparql #jena

#java #Oracle #rdf #sparql #jena

Вопрос:

Я пытаюсь изучить основы работы с тройками Jena и RDF. Также работаю с базой данных Oracle, поэтому, следуя их руководству, у меня есть несколько примеров запущенных программ, таких как Example7-18 SPARQL OPTIONAL Query. Пример работает нормально, как написано. Это позволяет сопоставлять запросы, такие как

 where {?s <u:parentOf> ?o}

where {<u:John> <u:parentOf> <u:Mary>}
 

Что я хотел бы сделать, так это указать возраст Джона, Мэри и Джилл каждому, чтобы я мог запрашивать и фильтровать по возрасту, как описано в SPARQL На примере: Шпаргалка, страница 10:

 A . B . FILTER ( …expr… )

where {?s <u:parentOf> ?o . ?o <u:isAge> ?a . filter ( ?a < 20 ) }
 

С текущим кодом для троек я могу добавлять только строки / узлы URI, и хотя я мог бы создать тройку, такую как <u:John> <u:isAge> <u:35> , я не могу фильтровать и сравнивать, например, с оператором < для этого возраста, поэтому это не очень полезно.

Я уже некоторое время осматриваюсь и подозреваю, что сделать это очень просто, но образцы кода было трудно найти.

Комментарии:

1. Обратите внимание, что текст, который нравится <u:John> <u:isAge> <u:35> , обрабатывается в редакторе как разметка, поэтому вам нужно окружить его обратными метками ` , иначе его никто не увидит. Я исправил это в этом случае.

Ответ №1:

Обратите внимание, что вам нужен объект типа "35"^^xsd:int or "35^^xsd:integer , который является литералами, а не <u:35> который является (возможно, искаженным) URI. Пример, на мой взгляд, делает что-то несколько необычным образом, и, согласно документации, он использует некоторые устаревшие методы. Во всяком случае, вы можете видеть, что он создает узлы URI с помощью методов из класса Node (заводского класса):

 Node.createURI("u:John")
Node.createURI("u:parentOf")
Node.createURI("u:Mary")
 

В классе Node существует пять методов createLiteral, и вы можете использовать createLiteral(String lex, RDFDatatype dtype) для создания литерала с типом данных. Однако этот метод устарел, и вместо него вам действительно следует использовать один из методов из NodeFactory.

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

 ModelOracleSem model = ModelOracleSem.createOracleSemModel(oracle, szModelName);
 

и эту задачу намного проще выполнить, если вы используете интерфейс модели, где у вас есть такие методы, как createTypedLiteral, чтобы вы могли просто вызвать createTypedLiteral(30) и получить обратно подходящий литерал. Вот пример:

 import java.math.BigInteger;

import com.hp.hpl.jena.query.Query;
import com.hp.hpl.jena.query.QueryExecution;
import com.hp.hpl.jena.query.QueryExecutionFactory;
import com.hp.hpl.jena.query.QueryFactory;
import com.hp.hpl.jena.query.ResultSetFormatter;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.rdf.model.Property;
import com.hp.hpl.jena.rdf.model.Resource;

public class CreateAndQueryExample {

    /**
     * @param args
     */
    public static void main(String[] args) {
        // You should be able to replace this with the Oracle model 
        // producing code.
        Model model = ModelFactory.createDefaultModel();

        Resource john = model.createResource( "urn:ex:John" );
        Resource mary = model.createResource( "urn:ex:Mary" );
        Property age = model.createProperty( "urn:ex:age" );

        // Using Model.add method
        model.add( john, age, model.createTypedLiteral( new BigInteger( "25" )));  // "25"^^xsd:integer
        // model.add( john, age, model.createTypedLiteral( 25 ));                  // "25"^^xsd:int
        // model.add( john, age, model.createTypedLiteral( 25l ));                 // "25"^^xsd:long

        // Using the Resource.addProperty method
        mary.addProperty( age, model.createTypedLiteral( new BigInteger( "35" )));

        Query query = QueryFactory.create( "select * where { ?s <urn:ex:age> ?age . filter ( ?age < 30 ) }" );
        QueryExecution exec = QueryExecutionFactory.create( query, model );
        ResultSetFormatter.out( exec.execSelect() );
    }
}
 
 -----------------------
| s             | age |
=======================
| <urn:ex:John> | 25  |
-----------------------
 

Комментарии:

1. Спасибо, это полезно, но вы не указали отношения ‘<parentOf>’ между ресурсами. Не могли бы вы добавить их также с помощью model.add, как если бы они были литералами? Какая разница, добавляю ли я свои отношения как литералы или как тройки?

2. @user985366 Я их не пропустил. В вашем вопросе был задан вопрос о добавлении возраста (целочисленных литералов) в тройки Jena RDF и выполнении запросов к ним с помощью SPARQL, и этот ответ показывает, как сделать обе эти вещи. У вас уже есть способ добавления узлов создания URI, и если вы хотите сделать это с помощью интерфейса модели и связанных интерфейсов, в ответе есть ссылки на эти интерфейсы.

3. Если вы собираетесь написать подобный шаблон ?s :parentOf ?o . ?o :hasAge ?a , то parentOf должен быть отношением между ресурсами (т.Е. Пустыми узлами и узлами URI, но не литералами). Литералы не могут быть предметом троек, поэтому, если вы использовали литерал в parentOf , например, :John :parentOf "Mary" , вам не повезло во второй тройке, потому что вы не можете сказать "Mary" :hasAge 25 .