1

我将模型存储在三重存储(持久性)中。我想选择与某个文档名称相关的所有个人。

我可以通过两种方式做到这一点

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 创建 Jena 的模型?

2) StmtIterator stmtIterator = model.listStatements(...)

这种方法的问题是我需要多次使用 model.listStatements(...) 操作:

a) 通过文档名称获取文档 URI

b) 获取与此文档 URI 相关的个人 ID 列表

c) finally - 得到一个个体的集合

我关心性能 - 3 次运行 model.listStatements(...) - 许多数据库请求。

或者在模型创建期间从数据库中将所有数据读入内存(我对此表示怀疑):

     Dataset ds = RdfStoreFactory.connectDataset(store, conn);
     GraphStore graphStore = GraphStoreFactory.create(ds) ;

?

4

1 回答 1

0

您需要稍作备份,并更清楚地考虑您要做什么。您的 sparql 查询一旦被纠正(见下文),将非常好地在结果集上生成一个迭代器,这将为您提供您正在寻找的每个文档的属性。s2具体来说,您会为每个和结果集中p2o2每个值获得一组绑定。这就是您在指定时所要求的select ?s2 ?p2 ?o2。这通常是您想要的:通常,我们从三重存储中选择一些值以便以某种方式处理它们(例如将它们呈现到 UI 上的列表中),为此我们确切地想要一个迭代结果。借助 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. 同样,不清楚为什么需要区分docs2:为什么不简单地将文档属性附加到doc资源?

最后:不,打开数据库连接不会将整个数据库加载到内存中。但是,TDB 确实广泛使用了图形区域的缓存,以提高查询效率。

于 2012-07-27T07:46:22.043 回答