如何编写SPARQL查询以高效地匹配字符串文字,同时忽略大小写

17

我正在使用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") )
}

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


你没有说你在使用哪个软件。许多RDF存储有文本索引选项,比regex()更适合文本搜索。 - Steve Harris
@SteveHarris 我更新了问题,包括我正在使用的技术。我最初希望只是错过了一些SPARQL功能,但现在我认为我需要像你建议的那样调查文本索引选项,所以谢谢你的提示。 - lmsurprenant
2个回答

19

在SPARQL中,你可以使用各种字符串操作符,但regex可能是最耗费资源的操作符之一。如果你避免使用regex并且在测试的两边使用UCASELCASE,你的查询可能会更快。例如:

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")
}

这可能会更快,但通常不要指望三元存储与任何文本搜索有很好的性能。三元存储在图匹配方面非常出色,但在字符串匹配方面表现不佳。


1
它可能会稍微快一些,但仍然比非过滤版本慢了几个数量级。感谢周到的回复,但我可能需要研究一下字符串索引选项。 - lmsurprenant
1
当我看到这个问题时,这正是我在寻找的答案。通过规范化字符串(通过小写)并进行检查,应该比正则表达式查询快得多。+1。 - Joshua Taylor

2
FILTER查询运行较慢的原因是因为?term未绑定,需要扫描PSO或POS索引以查找所有带有rdfs:label谓词的语句,并针对正则表达式进行过滤。当它绑定到具体资源时(在您的第一个示例中),它可以使用OPS或POS索引仅扫描具有rdfs:label谓词和指定对象资源的语句,这将具有更低的基数。
此类文本搜索问题的常见解决方案是使用外部文本索引。在这种情况下,Jena提供了一个名为LARQ的免费文本索引,它使用Lucene执行搜索并将结果与查询的其余部分连接起来。

1
这个答案是正确的,但它并没有提供最简单的答案来回答OP的问题“有没有更有效的方法来编写不区分大小写的查询?” msalvadores的答案表明,有一种比regex更有效的方法。 - Joshua Taylor

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接