过滤器
图形匹配可以找到图形中的模式。本节将介绍如何限制解决方案中的值。方法有很多,这里只介绍两种情况。
字符串匹配
SPARQL 提供基于正则表达式的字符串测试操作。 虽然正则表达式的语法与 SQL 不同,但它也能进行 SQL "LIKE "式的测试。
语法是:
FILTER regex(?x, "pattern" [, "flags"])
flags 参数是可选的。 flag "i " 表示模式匹配不区分大小写,如果要区分大小写,将第三个参数去掉就行,只保留 ?x 和匹配字符串两个参数就行。
示例查询 (q-f1.rq) 查找含有 "r "或 "R "的给定名称。
PREFIX vcard: <http://www.w3.org/2001/vcard-rdf/3.0#>
SELECT ?g
WHERE
{ ?y vcard:Given ?g .
FILTER regex(?g, "r", "i") }
结果如下:
-------------
| g |
=============
| "Rebecca" |
| "Sarah" |
-------------
正则表达式语言与 XQuery 正则表达式语言相同,后者是 Perl 中正则表达式语言的编码版本。
Java 代码如下:
import org.apache.jena.query.Query;
import org.apache.jena.query.QueryExecution;
import org.apache.jena.query.QueryExecutionFactory;
import org.apache.jena.query.QueryFactory;
import org.apache.jena.query.QuerySolution;
import org.apache.jena.query.ResultSet;
import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.ModelFactory;
public class Test03 {
static final String inputFileName = "java01/src/main/java/come/jena/rdf/vc-db-1.rdf";
public static void main(String[] args) {
// Load RDF data into a model
Model model = ModelFactory.createDefaultModel();
model.read(inputFileName); // Load your RDF data file
// Define a SPARQL query
String queryString = "PREFIX pr:<http://www.w3.org/2001/vcard-rdf/3.0#>" +
"SELECT ?g " +
"WHERE { ?y pr:Given ?g ." +
" FILTER regex(?g, \"r\", \"i\").}";
Query query = QueryFactory.create(queryString);
// Execute the query
try (QueryExecution qexec = QueryExecutionFactory.create(query, model)) {
ResultSet results = qexec.execSelect();
// Process the query results
while (results.hasNext()) {
QuerySolution soln = results.nextSolution();
System.out.println("?g: " + soln.get("?g"));
}
}
catch (Exception e){
e.printStackTrace();
}
}
}
运行结果:
测试值
有时,应用程序需要对变量值进行过滤。 在数据文件 vc-db-2.rdf 中,我们为年龄添加了一个额外字段。 年龄在 vCard 模式中没有定义,因此我们为本教程创建了一个新属性。 RDF 允许混合不同的信息定义,因为 URI 是唯一的。还要注意的是,info:age 属性的值是类型化的。
在这个数据摘录中,我们显示的是键入值。也可以写成普通 23。
<http://somewhere/RebeccaSmith/>
info:age "23"^^xsd:integer ;
vCard:FN "Becky Smith" ;
vCard:N [ vCard:Family "Smith" ;
vCard:Given "Rebecca" ] .
因此,要查找 24 岁以上的人的姓名的查询 (q-f2.rq) 是这样的:
PREFIX info: <http://somewhere/peopleInfo#>
SELECT ?resource
WHERE
{
?resource info:age ?age .
FILTER (?age >= 24)
}
算术表达式必须放在括号(圆括号)中。 唯一的解决方案是
---------------------------------
| resource |
=================================
| <http://somewhere/JohnSmith/> |
---------------------------------
只有一个匹配项,结果是 John Smith 的资源 URI。将这一轮搜索转向小于 24 岁的人,也有一个匹配结果,即 Rebecca Smith。 没有关于 Jones’s 一家的信息。
数据库中没有关于 Jones 的年龄信息:这些 vCard 上没有 info:age 属性,因此变量 age 没有取值,也就没有被过滤器测试。
Java 代码如下:
import org.apache.jena.query.Query;
import org.apache.jena.query.QueryExecution;
import org.apache.jena.query.QueryExecutionFactory;
import org.apache.jena.query.QueryFactory;
import org.apache.jena.query.QuerySolution;
import org.apache.jena.query.ResultSet;
import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.ModelFactory;
public class Test04 {
static final String inputFileName = "java01/src/main/java/come/jena/rdf/vc-db-2.rdf";
public static void main(String[] args) {
// Load RDF data into a model
Model model = ModelFactory.createDefaultModel();
model.read(inputFileName); // Load your RDF data file
// Define a SPARQL query
String queryString = "PREFIX pr:<http://www.w3.org/2001/vcard-rdf/3.0#>\n" +
"PREFIX info: <http://somewhere/peopleInfo#>" +
"SELECT ?resource " +
"WHERE { ?resource info:age ?age ." +
" FILTER (?age >= 23).}";
Query query = QueryFactory.create(queryString);
// Execute the query
try (QueryExecution qexec = QueryExecutionFactory.create(query, model)) {
ResultSet results = qexec.execSelect();
while (results.hasNext()) {
QuerySolution soln = results.nextSolution();
System.out.println("?resource: " + soln.get("?resource"));
}
}
catch (Exception e){
e.printStackTrace();
}
}
}
运行结果:
Jena 官方文档:https://jena.apache.org/tutorials/sparql_filters.html