选择页面

From semantic-mediawiki.org

Semantic MediaWiki之中语义搜索功能特性最为重要的部分就是,一种用来描述究竟应当把哪些页面显示为搜索结果的简单格式。 查询在选择维基页面时依据的是,利用类别(Categories)属性(Properties)以及可能还有页面的命名空间之类其他某些的MediaWiki功能而为查询所规定的那些信息。如下段落介绍的是SMW之中主要的查询功能。

类别与属性取值[edit]

入门示例里面,我们给出的是单独一个条件[[Located in::Germany]],用于描述我们所感兴趣的是哪些页面。 该标记文本正好就是在其他情况下您所要写出来的,用来断言特定页面具有该属性及该取值的标记文本。 而将其放在语义查询之中,则会使SMW返回所有此类的页面。 这是个通用的策略:查询那些满足某一条件的页面时所使用的语法,正好就是明确断言该条件成立时所使用的语法。

下列查询说明的就是这一点:

  1. [[Category:Actor]]:指出的是直接或(通过某个子类别、子子类别等等)间接地位于该类别(Actor,即演员)当中的所有页面。
  2. [[born in::Boston]]:指出的是标注为关于出生在波士顿(Boston)的某个人的所有页面。
  3. [[height::180cm]]:指出的是标注为关于身高为180cm的某个人的所有页面。

利用不同于上述情况的其他类别或属性,即可查询那些具有特定标注的页面。接下来,让我们把上述这些要求组合起来:

[[Category:Actor]] [[born in::Boston]] [[height::180cm]] 

这里,查询的就是所有身为演员出生在波士顿身高180cm的人。换句话说,当把许多条件同时写成一条查询的时候,结果就会缩小到那些满足全部这些要求的页面。因此,我们这里就有了一个逻辑和(logical AND)操作符。顺便提一下,为了让查询更加易读,其中还可以含有换行符。因此,上述查询亦可写作:

  [[Category:Actor]] 
  [[born in::Boston]] 
  [[height::180cm]]

这样,依然会获得相同的结果。 注意,查询只会返回那些肯定已知满足所需属性的文章:如果某位演员并没有身高属性,则不会选择该演员。

在指定属性取值的时候,SMW通常会忽略开头和结尾的任何空白(whitespace)。 因此,[[height::180cm]]与[[height:: 180cm ]],二者的含义相同。 数值之类的数据类型可能会具有额外的特点,比如,忽略那些可能用于分隔千分位的逗号。 SMW还会同等对待同义性的页面名称,就像MediaWiki通常认为Semantic wikiSemantic_wikisemantic wiki指的是同一页面那样。

如果您正在频繁地使用某些条件模式,不妨创建一个概念(Concept)作为快捷手段。概念构成的是某种虚拟的类别(virtual category),因而可以类似于类别条件(category conditions)那样来使用概念。

距离查询[edit]

如果安装了语义地图扩展的话,可将这种语法的一种特例用于查找具有一个地理坐标型取值,且该地点与某个指定位置相隔在一定距离范围内的所有页面。- 详情请参见Semantic Maps(语义地图)文档当中的距离查询页面。

属性取值:通配符与比较操作符[edit]

在上述的这些例子当中,我们采用属性取值«Boston»和«180cm»,给出了非常具体的属性条件。 在许多情况下,我们所查找并不仅仅是某个特定的取值,而是一个取值范围,如身高大于180cm的所有演员。 在有些情况下,则甚至可能查找的是特定属性具有任何取值的所有页面。例如,已故者可能就指的是那些死亡日期属性«date of death»具有取值的人。 利用比较操作符通配符,则可以列出此类的笼统条件。

通配符[edit]

通配符写作"+",指的是特定条件允许任何取值。例如,[[born in::+]]返回的是出生地属性«born in»具有任何取值的所有页面。

比较操作符[edit]

比较操作符是<>之类的特殊符号。 在属性条件里面,它们放在::后面。

  • >>:"大于"
  • <<:"小于"
  • >:默认为"大于等于",而当$smwStrictComparators = true;的时候,则为"大于"
  • <:默认为"小于等于",而当$smwStrictComparators = true;的时候,则为"小于"
  • :"大于等于"
  • :"小于等于"
  • !:"非"("不等于")
  • ~:«like»(类似于)字符串的模糊比较
  • !~:«not like»(不类似于)字符串的模糊比较

比较操作符仅适用于属性取值,而不能用于类别条件。维基站点安装可限制究竟哪些比较操作符可用;如配置页面所述,管理员只需更改$smwgQComparators的取值即可。

根据$smwStrictComparators取值的不同,对于><的解释可以有所不同;关于严格比较运算符的页面当中记载有这些不同的行为。

在对页面应用比较操作符时,使用的是页面的标题(不带命名空间前缀)。 不过,通过为相应页面设置另一个MediaWiki sortkey(排序键),如自定义键{{DEFAULTSORTKEY: custom key}},即可改变这种情况。 请注意,这适用于所有的比较操作符,包括!~。 一个页面不可拥有多个排序键(sortkeys)。特别是,在应用比较操作符的时候,并不考虑重定向页面。

不等于[edit]

您可以选择具有某一属性取值但其不等于特定取值的那些页面。比如:

  [[Area code::!415]]

这个查询示例选择的是那些具有面积代码但其取值不是«415»的页面。注意:该查询描述并不是要查找那些并不拥有面积代码415的页面,而查找的是的确也拥有面积代码但其取值不等于415的所有页面。尤其是,那些根本就不具有面积代码的页面不可能成为上述查询的结果。

与(默认)相等性比较操作符一样,自定义单位的使用可能在数值转换当中需要近似(rounding),而后者则可能导致意外的结果。例如,[[height::!6.00 ft]]可能仍旧选择的是其身高显示为«6.00 feet»的某个人,这只是因为其确切的数值实际上并不是6。 在此类情况下,更有用处的做法可能就是利用“<”和“>”进行多个条件的析取(参见下文)来表达,去查询那些具有超出特定范围的某一属性取值的页面。

大于等于,小于等于[edit]

对于数值型取值,您常常会想选择属性取值在特定范围内的那些页面。比如:

[[Category:Actor]] [[height::>6 ft]] [[height::<7 ft]]

其查询的是所有身高在6英尺与7英尺之间的演员。注意,这个例子利用了自动单位转换:即使是演员的身高设定成了[[height::195cm]], 亦可将其识别为正确的答案(假设身高的数据类型理解这两种单位,参见自定义单位)。注意,这里的比较操作符指的是大于等于/小于等于 – 但并不需要相等性符号=

当可以采取自然的方式对属性取值加以排序的话,此类关于属性取值的范围条件在大多数情况下是合适的。例如,我们可以询问[[start date::>May 6 2006]],但是要说[[homepage URL::>http://www.somewhere.org]]的话,那就真的没什么用处了。

如果一个数据类型没有自然的线性次序(linear ordering)的话,Semantic MediaWiki将仅仅对其规范化的数据取值(normalised datavalues )应用字母顺序,就像数据取值在RDF导出之中运用那样。这样,即可利用大于和小于来选择字符串型属性的字母型范围了。例如,可以通过询问[[surname::>Do]] [[surname::<G]],来选择位于«Do»乃至«G»之间的姓氏。对于维基页面,比较操作符处理的是指定页面的名称(不带命名空间前缀)。

包括这里的应用在内,在比较操作符所有其他的应用当中,可能会出现的情况就是,某个被搜索到的取值真的以<之类字符开头。在这种情况下,如果在::之后插入一个空格的话,即可避免SMW把这个符号解释成比较操作符。例如,[[property:: <br>]]实际上搜索的是指定属性取值为«<br>»的那些页面。

大于,小于[edit]

有时候,您可能会希望从结果本身当中排除掉某个确切的取值,比如,找出一位身高比Hugh Laurie(1.89m)高的演员,则您可以将比较操作符>!组合起来进行查询:

[[Category:Actor]] [[height::>1.89m]] [[height::!1.89m]]

类似于,不类似于[edit]

比较操作符~!~仅仅适用于数据类型为字符串(String)型的属性。在like条件里,采用通配符'*'来匹配任何的字符序列,而采用'?'来匹配任何单个的字符。例如,可通过询问"[[Address::~*Park Place*]]"来选择那些包含字符串«Park Place»的地址,或者利用"[[Honorific::~M?.]]"来同时选择«Mr.»与«Ms.»。

严格的比较操作符[edit]

SMW的这种默认行为,即比较操作符<>分别指的是"小于等于"和"大于等于",对于那些熟悉“<”和“>”的数学含义的人来说,可能在某种程度上会令人迷惑。因此,正如这里所述,您可以选择让SMW"严格地"解释“<”和“>”。

以特定符号开头的属性[edit]

特定属性的取值可能出现以下列符号开头的情况:<、≤、>、≥、=、!以及~。 SMW会将这些符号与内置的比较操作符相混淆。为了确保并不发生这种情况,属性因而对空白敏感(white-space sensitive)。 为避免混淆,在::之后要插入一个空格。 例如,[[property:: <br>]]实际上搜索的是那些特定属性的取值为"<br>"的页面

查询结果的并集:析取[edit]

析取(disjunctions )也就是逻辑或型的条件(OR-conditions),接受的是若干关于查询结果的备选条件。 SMW对查询之中的析取备有两种编写方式:

  • 操作符OR用于对两个查询取并集(union)。
  • 操作符||用于若干取值、页面及类别名称的析取。

在任何情况下,析取操作都需要至少满足一个可能的备选条件(但可能不止一个)逻辑或(logical OR)。例如:

[[born in::Boston]] OR [[born in::New York]]

该查询描述的是关于出生在BostonNew York的人的所有页面。该查询亦可采用||写作[[born in::Boston||New York]]。在后一种情况下,«Boston||New York»描述的是取值可能是两个备选项之一。通常,采用||来编写比较简洁,但并不是所有的析取操作均可采用这种方式来编写。如下示例就不能采用||来表达:

[[born in::Boston]] OR [[Category:Actor]]

|| 语法不仅可用于属性取值,亦可用于类别,就像在查询[[Category:Musical actor||Theatre actor]]当中那样。

具体单个页面的描述[edit]

到目前为止,所有的条件都取决于具体页面之中给出的这个或那个标注。但是,同时也有些条件可用于直接选择某些页面,或者是选择来自特定命名空间的页面。

直接给出某一页面的标题(可能其中含有某个命名空间前缀),或者利用以||为分隔符的此类页面标题列表,来选择具有这些名称的页面。这样的查询如:

[[Brazil||France||User:John Doe]]

该查询有三个结果(至少假设这些页面存在的话)。注意,结果并不现实任何的命名空间前缀;要确定相应的命名空间,可参见浏览器的悬停提示框(hover box)或状态栏,或者跟踪链接信息。在对基于特征属性取值(attribute value)的那个集合进行限制的时候,我们可以这样询问,比如,«Who of Bill Murray, Dan Aykroyd, Harold Ramis and Ernie Hudson is taller than 6ft?»。但是,假如询问的是这些文章进一步的属性,比如,打印输出Bill Murray的身高,那么直接选择相应文章的方法最为有用。

要采取这种方式来选择某个类别,则必须在类别名称之前放上一个:。这就可以避免[[Category:Actor]](返回所有的演员)与[[:Category:Actor]](仅仅返回演员类别«Actor»)的混淆。

将结果限制到特定的命名空间[edit]

一种较为宽松的用于选择特定页面的方法就是利用命名空间。默认情况是返回每个命名空间之中的页面。要返回某个特定命名空间之中的页面,请采用«通配符»来指定命名空间,如[[Help:+]]用于返回命名空间«Help»之中的所有页面。主命名空间通常没有前缀,只需[[:+]],即可仅仅选择主命名空间当中的所有页面。

析取再次与上述的||语法组合使用。例如,要返回主命名空间或«User»命名空间的话, 写成[[:+||User:+]]即可。要返回类别命名空间«Category»当中的页面,在命名空间之前也需要一个:,以防混淆,比如,[[:Category:+]]。

子查询与属性链[edit]

枚举一个属性的多个页面,既繁琐又难于维护。例如,为了选择所有出生在某个意大利城市的演员,可能就会写成如下查询:

[[Category:Actor]] [[born in::Rome||Milan||Turin||Florence||...]]

要生成所有这些意大利城市的列表,则可以运行另一个查询:

[[Category:City]] [[located in::Italy]]

然后,再把这个的结果复制并粘贴到第一个查询当中。 我们所希望做的就是,把上述城市查询作为演员查询的子查询,以便直接获得所需的结果。 不是采用属性取值相应页面名称的固定列表,而是将一个由<q>好</q>括起来的新查询插入在属性条件之中。对于当前的例子,因而可以写成下列形式:

[[Category:Actor]] [[born in::<q>[[Category:City]] [[located in::Italy]]</q>]]

任意层数的嵌套都可以,尽管特定的网站为了确保性能,可能会对嵌套加以限制。再举一例,要选择欧盟的所有城市时,可以这样写:

  [[Category:Cities]]
  [[located in::<q>[[member of::European Union]]</q>]]

该查询的实际运行结果: (查看结果)

在上述这个例子当中,实质上我们构建出的是«located in»与«member of»组成的一个属性,旨在找出那些位于某个欧盟成员内的事物。对于这种常见的情况,可将查询简写为:

[[Category:Cities]] [[located in.member of::European Union]]

这个查询与前者含义相同,但所需的特殊符号要少得多。一般来说,属性链是利用点(英文句号)把所有属性分隔罗列出来而形成的。 在罕见的情况下,属性的名称之中可能会包含点(英文句号);这时,可以让查询以空格开头,从而防止SMW按照上述特殊的方式来解释这个点(英文句号)。

注意:不能利用子查询来获取一张属性列表,而后又将该列表用在某个查询当中。参见如下的#对于属性的子查询一节。

模板和变量的使用[edit]

查询当中可使用任意的模板变量。 一个例子就是,用于根据当前日期来显示所有未来事件的选择条件:

 [[Category:Event]]
 [[end date::>{{CURRENTYEAR}}-{{CURRENTMONTH}}-{{CURRENTDAY}}]]

对于嵌入式查询来说,另一个尤为有用的变量就是,当前页面带有命名空间的页面全称{{FULLPAGENAME}};该变量可在许多页面上重复利用一个通用的查询。关于这一点的示例,请参见Property:Population。更多详情请参阅行内查询

结果的排序[edit]

采用合适的顺序来呈现查询结果往往会有所裨益。比如,按人口数量来呈现城市列表。 Special:Ask页面备有一个简单的界面,用于向查询当中添加一个或多个排序条件。 在文本输入栏当中输入要作为排序依据的属性的名称,且可以选择升序还是降序。 SMW通常会尝试按照所选属性取值的自然顺序来进行结果排序:

因此,这种次序与查询当中比较操作符 < 和 > 的情况相同。如果没有提供特定的排序条件,就会按照其页面名称来排序。

可以提供不止一个排序条件。如果相对于第一个排序条件,多个结果最终是同等次序的话,就会采用下一个条件来排序结果,依此类推等等。 例如,利用如下查询,我们可以获得一张按照其年平均降雨天数排序的城市列表,而又按城市所在国家来分组:

{{#ask: [[Category:City]]
|?Located in=Country
|?Average rainy days
|sort=Located in,Average rainy days
|order=ASC,DESC }}

如下为该查询实际的运行结果:

 CountryAverage rainy days
SydneyAustralia143.7
ViennaAustria88
KarlsruheBaden-Württemberg124
StuttgartBaden-Württemberg
Germany
112.4
San DiegoCalifornia
United States of America
29.4
LondonEngland145
ParisFrance111.5
WürzburgGermany156
CologneGermany132.5
MunichGermany129.4
FrankfurtGermany108.9
BerlinGermany106.3
RomeItaly84.5
AmsterdamNetherlands234
WarsawPoland159
PortoPortugal140

对于查询的排序亦可影响查询的结果,因为只能按照页面所实际拥有的属性取值来排序。 因此,假如按照某个属性(比如说«Population»)来对查询进行排序的话, SMW则通常会把查询结果限制到至少拥有该属性一个取值的那些页面(也就是说,结果当中出现的仅仅是那些具有所指定人口数量属性的页面)。因此,如果查询当中并没有要求每项查询结果之中都存在该属性,而SMW却会悄悄地在其中添加这个条件。但是,SMW总是会首先在所指定的查询之中查找出排序属性,甚至可以按照子属性来排序查询结果。下列示例应该可以说明这一点:

  • [[Category:City]] [[Population::+]]按«Population»来排序,将会按照人口数量以升序的方式来呈现这些城市。查询结果与不加排序时相同。
  • [[Category:City]]按«Population»来排序,仍会按照人口数量以升序的方式来呈现这些城市。查询结果则可能因为排序条件而有所变化:如果有些城市没有被给出人口数量,则结果里面就不再会出现这些城市。
  • [[Category:City]] [[has location country.population::+]]按«Population»来排序,将会按照城市所在国家的人口数量来呈现这些城市。查询结果并无变化,但«population»现在指的是子查询之中所使用的一个属性。

如果一个用于排序的属性在某个页面当中有不止一个取值,则该页面仍会出现在结果列表里面,只不过仅仅出现一次。SMW并没有规定在这种情况下该页面所要占据的位置,而其位置可能对应于该属性这些取值之中的任何一个。在上述那些示例之中,如果一个城市拥有多个被指定的人口数量,或者如果一个城市位于多个分别有着各自人口数量的国家,就会出现这种情况。建议要避免此类情况。

在查询结果表格里面,点击每列表头之中的小图标,亦可对查询结果加以动态排序。 这项功能需要浏览器之中启用了JavaScript,而且仅仅对所显示的结果进行排序。 因此,比如,如果一个查询检索到了按人口数量来说的20个世界最大城市,那么,就有可能采用字母顺序或者按人口数量降序,对这20个城市进行排序。但是,当逆转人口数量列的顺序时,该查询肯定不会显示20个最小城市。 表格的动态排序会尝试采用与SMW查询当中所采用的相同顺序,尤其是采用自然方式来排序数字和日期。然而,字符串和页面名称的字母顺序可能会与维基站点的字母顺序稍有不同,这只是因为根据语言首选项的不同,有着许多可以采用不同方式来排序的国际字母表。

链接到语义搜索结果[edit]

如相应的文档所述,可利用SMW之中的行内查询功能,来创建指向Special:Ask页面上语义查询结果的链接。 不推荐直接去创建链接,因为这种链接非常长,要使用一种特殊的编码。 那些创建指向Special:Ask页面的扩展的开发人员,也应当采用SMW的内部函数(internal functions)来构建此类链接。 因此,对于使用SMW来说,并不需要去理解SMW对链接之中的查询进行编码的细节。

不可能的事情[edit]

对于文本型属性的查询[edit]

您无法对文本("Text")型属性进行查询 - 此类查询将返回的是相应属性具有任何取值的所有页面。换言之,{{#ask: [[Foo::Bar]]}}的行为与{{#ask: [[Foo::+]]}}完全相同。

对于属性的子查询[edit]

不能利用子查询来获取一张属性列表,而后又将该列表用在某个查询当中。不过,倒是可以先采用一个查询返回一张属性列表,而后再将其结果复制并粘贴到另一个查询当中。另外一种方法就是,可利用模板结果格式向另一查询直接传递属性。

对于特殊属性的查询[edit]

当前,SMW并不支持那些对于SMW内置的«Has type»、«Allows value»或«Equivalent URI»之类任何特殊属性的取值的查询。