关于rdf:如何编写SPARQL查询以在不区分大小写的情况下有效地匹配字符串文字

How to write SPARQL query that efficiently matches string literals while ignoring case

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

1
2
3
4
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 .
}

这很好用,并且实际上非常快(<1秒)。不幸的是,对于某些术语,我需要以不区分大小写的方式执行此查询。例如,由于标签"Tylenol"在本体中,而不在"Tylenol"中,因此以下查询为空:

1
2
3
4
SELECT DISTINCT ?type WHERE {
 ?x <http://www.w3.org/2000/01/rdf-schema#label>"tylenol" .
 ?x <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> ?type .
}

我可以使用FILTER语法编写此查询的不区分大小写的版本,如下所示:

1
2
3
4
5
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") )
}

但是现在查询要花一分钟多的时间才能完成!有什么方法可以更有效地编写不区分大小写的查询?


在SPARQL中可以使用的所有可能的字符串运算符中,regex可能是最昂贵的。如果避免使用regex,而在测试的两边都使用UCASELCASE,则查询的运行速度可能会更快。类似于:

1
2
3
4
5
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")
}

这可能会更快,但通常不会期望在任何三重存储的文本搜索中都有出色的性能。三元存储非常擅长图匹配,而不太擅长字符串匹配。


使用FILTER查询的查询运行较慢的原因是因为?term是未绑定的,因此它需要扫描PSO或POS索引以查找所有带有rdfs:label谓词的语句,并根据正则表达式对其进行过滤。当将其绑定到具体资源时(在第一个示例中),它可以使用OPS或POS索引仅扫描具有rdfs:label谓词和指定对象资源的语句,该语句的基数要低得多。 >

这种类型的文本搜索问题的常见解决方案是使用外部文本索引。在这种情况下,Jena提供了一个称为LARQ的自由文本索引,该索引使用Lucene进行搜索,并将结果与??其余查询结合在一起。