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, в частности, широко использует кэширование областей графа, чтобы сделать запросы более эффективными.

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