6.11.2. 通过SQL Server查询Index Server
如果要通过SQL Server查询Index Server,须使用OPENQUERY函数。其语法结构如下。
OPENQUERY(linked_server, 'query')
其中linked_server参数为连接的名称。而query参数为要进行的查询,它将以一个字符串的形式传送给OPENQUERY函数。此函数返回的将是一个虚拟表,从而可以让我们对其做进一步的查询。
下面的语句查找内容包含中SQL这个单词的所有文件:
SELECT *
FROM OpenQuery(FileSystem,
'SELECT Directory, FileName, DocAuthor, Size, Create
FROM SCOPE()
WHERE CONTAINS( Contents, ''SQL'' ) ' )
对于Index Server的查询,其FROM语句的语法格式于普通的SQL语句是有所区别的。其语法结构如下:
FROM [ Catalog_Name.. ] { SCOPE( [ 'Scope_Arguments' ] ) }
其中的Catalog_Name参数用于指明要进行查询的索引目录。由于我们在定义连接时只能选择一个索引目录,所以此参数在此将被省略。而SCOPE函数用于指明要进行查询的文件所在的目录。SCOPE函数的语法结构如下图所示。
图6.11.2-1SCOPE函数语法结构图
其中DEEP TRAVERSAL OF关键字指明将查询目录中所有的文件,包括其子目录中的所有文件。而SHALLOW TRAVERSAL OF关键字则指明只查询顶级目录中的文件,而不包括子目录中的那些文件。如果不指明查询的目录深度,则默认为DEEP TRAVERSAL OF。
physical_path和virtual_directory分别为物理目录和虚拟目录。其中各自的含义在图中已经标示的非常明白了,在此就不再进一步说明了。
Index Server共支持50种文件属性,而可以用来作为查询条件或返回结果的常用文件属性见下表:
属性名称 数据类型 注释 可否用于ORDER BY子句 可否用于SELECT语句中
Access datetime 文件的最后访问时间。 可 可
Characterization nvarchar或ntext 文档的描述或摘要,由Index Server使用。 否 可
Create datetime 文件的创建时间。 可 可
Directory Nvarchar 文件的物理路径,不包含文件名。 可 可
DocAppName nvarchar 创建文件的应用程序的名称。如Microsoft Word 9.0。 可 可
DocAuthor nvarchar 文档的作者。 可 可
DocComments nvarchar 关于文档的注释。 可 可
DocCompany nvarchar 写作文档的公司的名称。 可 可
DocLastAuthor nvarchar 最近编辑文档的用户。 可 可
DocLastPrinted datetime 文档的最近一次打印时间。 可 否
DocPageCount integer 文档的页数。 可 否
DocParaCount integer 文档的图形数量。 可 否
DocRevNumber integer 文档的当前版本。 可 可
DocSubject nvarchar 文档的主题。 可 可
DocTemplate nvarchar 文档的模板。 可 可
DocTitle nvarchar 文档的标题。 可 可
DocWordCount integer 文档的字数。 可 否
FileIndex Decimal(19,0) 文件的唯一标识。 可 可
FileName nvarchar 文件名。 可 可
HitCount integer 文件中的命中次数(单词匹配查询)。即文件中有多少个查询条件中的单词。 可 可
Path nvarchar 文件的物理路径,包含文件名。 可 可
Rank integer 行的等级,范围从 0 到 1000,数字越大表示越匹配。 可 可
ShortFileName nvarchar 短文件名(8.3格式)。 可 可
Size Decimal(19,0) 文件大小,单位是字节。 可 可
VPath nvarchar 指向文件的完整虚拟路径,包括文件名。如果有多个可能的路径,将选择最符合查询的一个。 可 可
Write datetime 最近一次写文件的时间。 可 可
可以在Where子句中使用以上各种属性作为查询的条件。当条件中包含全文检索条件时,需要使用CONTAINS和FREETEXT语句,其用法同SQL Server的全文检索相同。要注意的是,在对Index Server的查询中,不能使用GROUP BY和HAVING子句。因为这不被Index Server所支持。
此外,在查询的SELECT子句中,不能使用*来选择所有的属性。*只有在对视图进行查询时才可以使用。视图实际上可以理解为从一个查询导出的虚拟表。通过对视图的查询,可以实现对查询结果的再次查询。视图一般应用于需要经常被其他查询作为FROM子句中的数据源时使用。建立视图使用CREATE VIEW语句,其语法结构如下:
CREATE VIEW view_name [(column ][,...n])]
AS
select_statement
其中view_name为要建立的视图的名称,而AS子句后面的就是建立视图的查询语句。而此语句有以下限制:不能包含ORDER BY、COMPUTE和COMPUTE BY等子句;不能包含INTO关键字;不能涉及临时表。
而column则用于为视图中的各个字段命名。一般只有在这些字段是表达式或函数及常数时才需要为其命名。
在SQL Server中,也同样可以使用CREATE VIEW语句来建立视图。
下面我们通过一个例子来了解对Index Server查询的全部过程。
我们将在虚拟目录\Corpus和C:\temp目录中查找那些作者在writer表中存在记录且文档字数超过5000字的文件。并返回作者的名字、文档题目以及作者的身份。其查询语句和具体操作过程如下图所示。
图6.11.2-2Index Server查询过程
其中各个步骤的解释如下:
1:查询被提交到SQL Server,将分布式查询部分(包含在OPENQUERY函数之内的部分)传递给SQL Server分布式查询处理器。
2:分布式查询处理器将查询进一步传递给OLE DB Provider for Indexing Service(MSIDXS),由MSIDX连接到文件系统。
3:MSIDXS分析查询语句并向文件索引服务发出相应的命令。
4:文件索引服务从一个结合了Web虚拟目录/Corpus和C:\Temp目录的虚拟表中查找那些符合条件的文件并将其作为一个行集返回给MSIDX。
5:MSIDXS将行集返回给分布式查询处理器。
6:分布式查询处理器将返回的行集作为一个表同writers表进行结合查询,并将最终结果返回给查询提交者。
在对Index Server的查询中,还不能使用QUANTIFIED、COMPARISON、BETWEEN、EXISTS、IN以及NULL等谓词。因为这些都不被Index Server所支持。但是它支持两个SQL Server所不直接支持的两个谓词:MATCHES和ARRAY。我们可以在对Index Server的查询语句中使用它们。其含义和语法结构分别如下:
MATCHES:用于模式匹配,其作用同Like相近但是功能更为强大。它的语法结构如下:MATCHES (Column_Reference, ' { Grouped_Search_Pattern | Counted_Search_Pattern } ') > 0
其中Column_Reference为指定的文件属性,其数据类型必须同后面的Grouped_Search_Pattern相匹配。
Grouped_Search_Pattern为指定的匹配模式。而Counted_Search_Pattern则用于对匹配的数量进行限定,可以有三种限定方式:
严格匹配:在查询的文件属性中包含指定数目的满足匹配条件的字串。
至少匹配:在查询的文件属性中包含大于或等于指定数目的满足匹配条件的字串。
范围匹配:在查询的文件属性中包含满足匹配条件的字串数目界于n~m之间。
MATCHES可以使用的模式匹配符及其含义见下表:
符号 描述
* 包含指定的匹配字符串同时还包含其他0个或更多的字符。这同dir命令中使用的*十分类似。如以b开头,以d结尾的字符串的匹配条件为b|*d。
? 包含指定的匹配字符串同时还包含其他0个或一个字符。如满足b|?d匹配条件的字串包括bd、bad和bed等。
+ 包含指定的匹配字符串同时还包含其他1个或更多的字符。如满足b|+d匹配条件的字串包括bad、bed和bond等。
( ) 用于界定模式匹配,表明在其中的是模式匹配字符条件。当条件多于一个时使用。
{ } 用于界定匹配数量,表明在其中的是模式匹配数量条件。
[ ] 用来在模式条件中指明一个字符串的范围。
| 一个转义符,要求在上面的每个符号前使用它。从而将其同普通字符区别开来。
下面通过几个简单的例子来说明MATCHES谓词的使用方法。
查找文件内容中出现"SQL"三次的文件:
...WHERE MATCHES (DocText, '|(SQL|)|{3|}' ) > 0
查找文件内容中出现"SQL"三次以上的文件:
...WHERE MATCHES (DocText, '|(SQL|)|{3,|}' ) > 0
查找文件内容中出现"SQL"三次到十次之间的文件:
...WHERE MATCHES (DocText, '|(Bora|)|{3,10|}' ) > 0
当你不能确定作者姓名中包含"Pellow"还是"Pelow"时,可以使用下面的条件语句:
...WHERE MATCHES( DocAuthor, '* Pel|{1,2|}ow' ) > 0
ARRAY:用于在两个排列(也称为矢量)之间通过逻辑运算符来进行比较。其语法结构如下:
Column_Reference Comparison_Operator [ ALL | SOME ] ARRAY [ Array_Elements ]
其中Column_Reference用于比较的文件属性,可以是多个属性。但是要求其数据类型同后面的Array_Elements相匹配。
Comparison_Operator为比较运算符,它可以是=、!=(不等于)、>、=>、<、<=。
Array_Elements用于指明用于进行比较的排列,其必须用"[]"括起来。空的排列也是允许的,比如下面的查询也是合法的。
SELECT foo FROM SCOPE() WHERE bar = ARRAY[]
ALL和SOME则用来指明对Array_Elements使用不同的比较方式。对于All,将会对左侧排列中的每个元素同右侧排列中相应的元素进行比较。比如下面的表达式对于ALL,表达式结果为假:
[1,2,3] > ALL ARRAY [1,2]
而对于SOME,则只要在左侧排列中有一个值同右侧排列中所有的值比较复合条件即可。因此下面的表达式对于SOME,其表达式结果为真:
[1,2,3] > SOME ARRAY [2,1]
因为在左侧排列中的3,比右侧排列中的2和1都大因此返回值为真。
如果不指明ALL或SOME,将会按照从左至右的顺序对表达式左侧排列中的元素同右侧中相应的元素进行比较。而一旦两者不同,将直接返回比较结果而不再继续进行其他元素的比较。而如果所有比较的值都相等,则根据排列的势来决定最后的比较结果。因此下列表达式的值都为真。
ARRAY [2,3,4] > ARRAY [1,2]
ARRAY [2,3,4] > ARRAY [1,2,3]
ARRAY [2,3,4] > ARRAY [1,2,3,4]
ARRAY [2,3,4] > ARRAY [1,2,5]
ARRAY [2,3,4] > ARRAY [2,3,3]
ARRAY [2,3,4] > ARRAY [2,3]
ARRAY [2,3,4] < ARRAY [2,3,4,5]
ARRAY [2,3,4]!= ARRAY [2,3,4,5]
下面通过几个例子来说明ARRAY谓词的使用方法:
查找所有文件属性为"存档"的文件:
...WHERE attrib = ARRAY [ 0X820 ]
查找所有文件属性为"存档"或"压缩"(针对于NTFS文件系统)的文件:
...WHERE attrib = SOME ARRAY [0X820 ]
查找矢量值为[10,15,20]的ActiveX文档:
...WHERE vectorprop = ARRAY [10, 15, 20]
(出处:不详 )