Rdf 如何编写SPARQL查询,在忽略大小写的同时有效地匹配字符串文本

Rdf 如何编写SPARQL查询,在忽略大小写的同时有效地匹配字符串文本,rdf,sparql,jena,arq,tdb,Rdf,Sparql,Jena,Arq,Tdb,我正在使用Jena ARQ针对从Jena TDB读取的大型本体编写SPARQL查询,以便根据rdfs标签查找与概念相关的类型: SELECT DISTINCT ?type WHERE { ?x <http://www.w3.org/2000/01/rdf-schema#label> "aspirin" . ?x <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> ?type . } 我可以使用如下筛选器语法编写此查询的

我正在使用Jena ARQ针对从Jena TDB读取的大型本体编写SPARQL查询,以便根据rdfs标签查找与概念相关的类型:

SELECT DISTINCT ?type WHERE {
 ?x <http://www.w3.org/2000/01/rdf-schema#label> "aspirin" .
 ?x <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> ?type .
}
我可以使用如下筛选器语法编写此查询的不区分大小写的版本:

SELECT DISTINCT ?type WHERE {
 ?x <http://www.w3.org/2000/01/rdf-schema#label> ?term .
 ?x <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> ?type .
 FILTER ( regex (str(?term), "tylenol", "i") )
}
选择DISTINCT?类型,其中{
?x?术语。
?x?型。
过滤器(正则表达式(str(?term),“tylenol”,“i”))
}

但是现在查询需要一分钟才能完成!有没有更有效的方法来编写不区分大小写的查询?

在SPARQL中可以使用的所有可能的字符串运算符中,
regex
可能是最昂贵的。如果您避免使用
regex
,而是在测试的两侧使用
UCASE
LCASE
,则查询可能会运行得更快。比如:

SELECT DISTINCT ?type WHERE {
 ?x <http://www.w3.org/2000/01/rdf-schema#label> ?term .
 ?x <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> ?type .
 FILTER (lcase(str(?term)) = "tylenol")
}
选择DISTINCT?类型,其中{
?x?术语。
?x?型。
过滤器(lcase(str(?term))=“泰诺”)
}

这可能会更快,但一般来说,使用任何三重存储的文本搜索都不会有很好的性能。三重存储非常擅长于图匹配,而不太擅长于字符串匹配

带有筛选器查询的查询运行较慢的原因是?术语未绑定。它需要扫描PSO或POS索引,以查找带有rdfs:label谓词的所有语句,并根据正则表达式对它们进行筛选。当它绑定到一个具体的资源时(在第一个示例中),它可以使用OPS或POS索引只扫描带有rdfs:label谓词和指定对象资源的语句,这将具有更低的基数


这类文本搜索问题的常见解决方案是使用外部文本索引。在本例中,Jena提供了一个名为的自由文本索引,该索引使用Lucene执行搜索,并将结果与查询的其余部分连接起来。

您不需要说明正在使用的软件。许多RDF存储都有文本索引选项,这些选项比regex()更能有效地进行文本搜索。@SteveHarris我更新了这个问题,加入了我正在使用的技术。我原本希望我只是错过了一些SPARQL特性,但现在我“我想我需要像你建议的那样调查文本索引选项,所以谢谢你的提示。它可能会稍微快一点,但仍然比非过滤版本慢几个数量级。谢谢你周到的回答,但我可能需要研究字符串索引选项。当我看到这个问题时,这正是我想要的答案。规范化字符串(通过下套管)和检查应该比正则表达式查询快得多+1.这个答案是正确的,但它并没有为OP的问题提供最简单的答案“有没有更有效的方法来编写不区分大小写的查询?”表明有一种方法比
regex
更有效。
SELECT DISTINCT ?type WHERE {
 ?x <http://www.w3.org/2000/01/rdf-schema#label> ?term .
 ?x <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> ?type .
 FILTER (lcase(str(?term)) = "tylenol")
}