跳转到内容

SPARQL/FILTER

来自维基教科书,自由的教科书

FILTER(condition) 是可以插入 SPARQL 查询中的一个子句,用于过滤结果。在括号内,您可以放置任何布尔类型的表达式,并且只有表达式返回 true 的结果才会被使用。

根据值过滤

[编辑 | 编辑源代码]

例如,要获取 2015 年出生的所有人类列表,我们首先获取所有人类及其出生日期 -

SELECT ?person ?personLabel ?dob
WHERE
{
  ?person wdt:P31 wd:Q5;
          wdt:P569 ?dob.
  SERVICE wikibase:label { bd:serviceParam wikibase:language "en". } 
}

- 然后过滤结果,只返回出生日期年份为 2015 的结果。有两种方法可以做到这一点:使用 YEAR 函数提取日期的年份,并测试它是否为 2015 -

FILTER(YEAR(?dob) = 2015).

- 或者检查日期是否在 2015 年 1 月 1 日(含)和 2016 年 1 月 1 日(不含)之间。

FILTER("2015-01-01"^^xsd:dateTime <= ?dob && ?dob < "2016-01-01"^^xsd:dateTime).

我认为第一种方法更直接,但事实证明第二种方法快得多,所以让我们使用它。

SELECT ?person ?personLabel ?dob
WHERE
{
  ?person wdt:P31 wd:Q5;
          wdt:P569 ?dob.
  FILTER("2015-01-01"^^xsd:dateTime <= ?dob && ?dob < "2016-01-01"^^xsd:dateTime).
  SERVICE wikibase:label { bd:serviceParam wikibase:language "en". } 
}

试试吧!

根据标签中的值过滤

[编辑 | 编辑源代码]

FILTER 的另一个可能用法与标签相关。标签服务非常有用,如果您只是想显示变量的标签。但如果您想对标签做一些操作 - 例如:检查它是否以 “Mr. ” 开头 - 您会发现它不起作用。

SELECT ?human ?humanLabel
WHERE
{
  ?human wdt:P31 wd:Q15632617.                # fictional human
  SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
  FILTER(STRSTARTS(?humanLabel, "Mr. ")).     # This does not work
}

试试吧!

此查询查找所有 Q15632617 的实例,并测试它们的标签是否以 "Mr. " 开头(STRSTARTS 是 “字符串开头 [以]” 的缩写;还有 STRENDSCONTAINS)。此方法不起作用的原因是标签服务在查询评估期间非常晚才添加其变量;在我们尝试根据 ?humanLabel 过滤时,标签服务尚未创建该变量。

幸运的是,标签服务不是获取项目标签的唯一方法。标签也以普通三元组的形式存储,使用谓词 rdfs:label。当然,这意味着所有标签,而不仅仅是英文标签;如果我们只想要英文标签,我们将不得不根据标签的语言进行过滤。

FILTER(LANG(?label) = "en").

LANG 函数返回单语字符串的语言,在这里我们只选择那些用英文表示的标签。完整的查询是

SELECT ?human ?humanLabel
WHERE
{
  ?human wdt:P31 wd:Q15632617;  # fictional human
         rdfs:label ?humanLabel.
  FILTER(LANG(?humanLabel) = "en").
  FILTER(STRSTARTS(?humanLabel, "Mr. ")).
}

试试吧!

我们使用 ?human rdfs:label ?label 三元组获取标签,将其限制为英文标签,然后检查它是否以 “Mr. ” 开头。

FILTER NOT EXISTS

[编辑 | 编辑源代码]

让我们为这些虚构的人添加图像。

SELECT ?human ?humanLabel ?image
WHERE
{
  ?human wdt:P31 wd:Q15632617;  # fictional human
         rdfs:label ?humanLabel.
  FILTER(LANG(?humanLabel) = "en").
  FILTER(STRSTARTS(?humanLabel, "Mr. ")).
  OPTIONAL{ ?human wdt:P18 ?image. }
}

试试吧!

代码 OPTIONAL{ ?human wdt:P18 ?image. } 显示了所有以 “Mr. ” 开头的虚构人物,如果可用,则显示图像。
要仅选择以 “Mr. ” 开头的带有图像的虚构人物,可以使用代码 ?human wdt:P18 ?image.
要选择那些没有图像的虚构人物,应使用代码 FILTER NOT EXISTS{ ?human wdt:P18 ?image. }

SELECT ?human ?humanLabel ?image
WHERE
{
  ?human wdt:P31 wd:Q15632617;  # fictional human
         rdfs:label ?humanLabel.
  FILTER(LANG(?humanLabel) = "en").
  FILTER(STRSTARTS(?humanLabel, "Mr. ")).
  FILTER NOT EXISTS{ ?human wdt:P18 ?image. }  # without images
}

试试吧!

SPARQL 中提供的另一种否定方式是 MINUS,它会评估其两个参数,然后计算左侧的解决方案,这些解决方案与右侧的解决方案不兼容。

SELECT ?human ?humanLabel ?image
WHERE
{
  ?human wdt:P31 wd:Q15632617;  # fictional human
         rdfs:label ?humanLabel.
  FILTER(LANG(?humanLabel) = "en").
  FILTER(STRSTARTS(?humanLabel, "Mr. ")).
  MINUS{ ?human wdt:P18 ?image. }  # without images
}

试试吧!

参考文献

[编辑 | 编辑源代码]


华夏公益教科书