我将模型存储在三重存储(持久性)中。我想选择所有与某个文档名称相关的个人。
我可以用两种方法
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) 最后-获得个人的集合
我关心性能-3次运行model.listStatements(…)-许多数据库请求。
或者在模型创建过程中,所有数据都从数据库读取到内存中(我对此表示怀疑):
Dataset ds = RdfStoreFactory.connectDataset(store, conn);
GraphStore graphStore = GraphStoreFactory.create(ds) ;
您需要做一点备份,并更清楚地思考您要做什么。您的sparql查询一旦得到更正(见下文),将在结果集上生成一个迭代器,它将为您提供您要查找的每个文档的属性。具体来说,对于结果集中的每个值,您将为s2
、p2
和o2
中的每一个获得一组绑定。这就是您在指定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
。同样,也不清楚为什么需要区分doc
和s2
:为什么不简单地将文档属性附加到doc
资源?
最后:不,打开数据库连接不会将整个数据库加载到内存中。然而,TDB确实广泛使用了图的区域缓存,以提高查询效率。