我正在使用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 .
}
这工作得很好,实际上非常快(<1秒(。 不幸的是,对于某些术语,我需要以不区分大小写的方式执行此查询。 例如,由于标签"Tylenol"
在本体中,但不"tylenol"
,因此以下查询为空:
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 语法编写此查询的不区分大小写的版本,如下所示:
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
并在测试的两端都使用 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")
}
这可能更快,但通常不要期望使用任何三重存储进行文本搜索时具有出色的性能。三重存储非常擅长图形匹配,不太擅长字符串匹配。
带有 FILTER 查询的查询运行速度较慢的原因是 ?term 未绑定,它需要扫描 PSO 或 POS 索引以查找所有带有 rdfs:label 谓词的语句,并根据正则表达式过滤它们。 当它绑定到具体资源时(在您的第一个示例中(,它可以使用 OPS 或 POS 索引仅扫描具有 rdfs:label 谓词和指定对象资源的语句,这些语句的基数要低得多。
此类文本搜索问题的常见解决方案是使用外部文本索引。 在本例中,Jena 提供了一个名为 LARQ 的自由文本索引,该索引使用 Lucene 执行搜索并将结果与查询的其余部分联接。