Jena StmtIterator и база данных
Моя модель хранится в тройном магазине (постоянство). Я хочу выбрать всех лиц, связанных каким-либо именем документа.
Я могу сделать это двумя способами
1) SPARQL-запрос:
PREFIX base:<http://example#>
select ?s2 ?p2 ?o2
where {
{?doc base:fullName <file:/c:/1.txt>; ?p1 ?o1
} UNION {
?s2 ?p2 ?o2 ;
base:documentID ?doc }
}
Вопрос: Как создать модель Джены из ResultSet?
2) StmtIterator stmtIterator = model.listStatements(...)
Проблема с этим подходом заключается в том, что мне нужно использовать операцию model.listStatements(...) несколько раз:
а) получить URI документа по имени документа
б) получить список физических лиц, связанных с этим документом URI
в) наконец - получить коллекцию лиц
Я беспокоюсь о производительности - 3 раза запустить model.listStatements(...) - много запросов к базе данных.
Или все данные считываются в память (я сомневаюсь в этом) из базы данных при создании модели:
Dataset ds = RdfStoreFactory.connectDataset(store, conn);
GraphStore graphStore = GraphStoreFactory.create(ds) ;
?
1 ответ
Вам нужно немного подкрепиться и более четко подумать о том, что вы пытаетесь сделать. Ваш запрос sparql, как только он будет исправлен (см. Ниже), отлично справится с задачей создания итератора для набора результатов, который предоставит вам свойства каждого из документов, которые вы ищете. В частности, вы получаете один набор привязок для каждого из s2
, p2
а также o2
для каждого значения в наборе результатов. Это то, что вы просите, когда вы указываете select ?s2 ?p2 ?o2
, Обычно это то, что вам нужно: обычно мы выбираем некоторые значения из тройного хранилища, чтобы каким-то образом обрабатывать их (например, отображать их в виде списка в пользовательском интерфейсе), и для этого нам нужен итератор для результатов. Вы можете сделать так, чтобы запрос возвращал вам модель, а не набор результатов, с помощью запроса конструкции SPARQL или описания SPARQL. Тем не менее, у вас возникает необходимость перебирать ресурсы в модели, так что вы не намного впереди (за исключением того, что ваша модель меньше и находится в памяти).
Ваш запрос, кстати, можно улучшить. Переменные p1
а также o1
заставить механизм запросов выполнять бесполезную работу, так как вы никогда не используете их, и нет необходимости в объединении. Исправлено, ваш запрос должен быть:
PREFIX base:<http://example#>
select ?s2 ?p2 ?o2
where {
?doc base:fullName <file:/c:/1.txt> .
?s2 base:documentID ?doc ;
?p2 ?o2 .
}
Чтобы выполнить любой запрос, выбрать, описать или построить, из Java см. Документацию Jena.
Вы можете эффективно достичь тех же результатов, что и ваш запрос, используя API модели. Например, (не проверено):
Model m = ..... ; // your model here
String baseNS = "http://example#";
Resource fileName = m.createResource( "file:/c:/1.txt" );
// create RDF property objects for the properties we need. This can be done in
// a vocab class, or automated with schemagen
Property fullName = m.createProperty( baseNS + "fullName" );
Property documentID = m.createProperty( baseNS + "documentID" );
// find the ?doc with the given fullName
for (ResIterator i = m.listSubjectsWithProperty( fullName, fileName ); i.hasNext(); ) {
Resource doc = i.next();
// find all of the ?s2 whose documentID is ?doc
for (StmtIterator j = m.listStatements( null, documentID, doc ); j.hasNext(); ) {
Resource s2 = j.next().getSubject();
// list the properties of ?s2
for (StmtIterator k = s2.listProperties(); k.hasNext(); ) {
Statement stmt = k.next();
Property p2 = stmt.getPredicate();
RDFNode o2 = stmt.getObject();
// do something with s2 p2 o2 ...
}
}
}
Обратите внимание, что ваш дизайн схемы делает это более сложным, чем должно быть. Если, например, ресурс полного имени документа имел base:isFullNameOf
собственности, то вы можете просто сделать поиск, чтобы получить doc
, Точно так же не понятно, почему нужно различать doc
а также s2
: почему бы просто не прикрепить свойства документа к doc
ресурс?
Наконец: нет, открытие соединения с базой данных не загружает всю БД в память. Однако TDB, в частности, широко использует кэширование областей графа, чтобы сделать запросы более эффективными.