Windows 搜索中的查询过程

本主题按如下所示进行组织:

Windows 搜索中的查询基于以下四种方法:

  • 高级查询语法 (AQS)
  • 自然查询语法 (NQS)
  • 结构化查询语言 (SQL)
  • 结构化查询接口

AQS 是 Windows 搜索用于查询索引和优化和缩小搜索参数的默认查询语法。 AQS 主要面向用户,可供用户用来生成 AQS 查询,但开发人员也可以使用它以编程方式生成查询。 在 Windows 7 中,引入了规范 AQS,必须用于以编程方式生成 AQS 查询。 在 Windows 7 及更高版本中,可以根据是否满足 AQS 条件提供快捷菜单选项。 有关详细信息,请参阅 创建上下文菜单处理程序中的“使用高级查询语法获取静态谓词的动态行为”。 AQS 查询可以限制为特定类型的文件,这些类型称为文件类型。 有关详细信息,请参阅 文件类型和关联。 有关相关属性的参考文档,请参阅 System.KindSystem.KindText

NQS 是比 AQS 更宽松的查询语法,类似于人类语言。 如果选择了 NQS 而不是默认 AQS,则 Windows 搜索可以使用 NQS 查询索引。

SQL 是定义查询的文本语言。 SQL 在许多不同的数据库技术中很常见。 Windows 搜索使用 SQL,实现它的子集,并通过向语言添加元素来扩展它。 Windows 搜索 SQL 扩展了标准的 SQL-92 和 SQL-99 数据库查询语法,以增强其基于文本的搜索的有用性。 Windows 搜索 SQL 的所有功能都与 Windows XP 和 Windows Server 2003 及更高版本的 Windows 搜索兼容。 有关 Windows 搜索 SQL 的详细信息,请参阅 使用 Windows 搜索 SQL 语法查询索引,以及 Windows 搜索 SQL 语法概述

本主题稍后将介绍结构化查询 API。 有关结构化查询 API 的参考文档,请参阅 查询接口 ISearchQueryHelper 等接口有助于从一组输入值构造 SQL 字符串。 此接口将 AQS 用户查询转换为 Windows 搜索 SQL,并指定可在 SQL 中表示但不能在 AQS 中表示的查询限制。 ISearchQueryHelper 还获取用于连接到 Windows 搜索数据库的 OLE DB 连接字符串。

本地和远程查询

可以在本地或远程执行查询。 以下示例显示了使用 FROM 子句 的本地查询。 本地查询仅查询本地 SystemIndex 目录。

FROM SystemIndex

以下示例显示了使用 FROM 子句 的远程查询。 添加 ComputerName 会将前面的示例转换为远程查询。

FROM [<ComputerName>.]SystemIndex

默认情况下,Windows XP 和 Windows Server 2003 未安装 Windows 搜索。 只有 Windows 搜索 4 (WS4) 提供远程查询支持。 早期版本的 Windows 桌面搜索(WDS)不支持远程查询,例如 3.01 及更早版本。 使用 Windows 资源管理器,可以查询远程计算机的本地索引来查找文件系统项(由“file:”协议处理的项目)。

若要通过远程查询检索项,该项必须满足以下要求:

  • 可通过通用命名约定 (UNC) 路径进行访问。
  • 存在于客户端有权访问的远程计算机上。
  • 将其安全设置为允许客户端具有读取权限。

Windows 资源管理器具有共享项目的功能,包括 网络和共享中心的“公共”共享(\\Machine\Public\...),以及通过共享向导共享的项目的“用户”共享(\\Machine\Users\...)。 共享文件夹后,可以通过在 FROM 子句中指定远程计算机的计算机名称以及 SCOPE 子句中远程计算机上的 UNC 路径来查询本地索引。 以下示例显示了使用 FROM 和 SCOPE 子句的远程查询。

SELECT System.ItemName FROM MachineName.SystemIndex WHERE SCOPE='file://MachineName/<path>' 

此处提供的示例使用 SQL。

结构化查询 API 概述

结构化查询通过对单个属性的查询的布尔组合来搜索信息。 本主题概述了最重要的结构化查询 API 和方法的功能。 有关结构化查询 API 的参考文档,请参阅 查询接口

IQueryParser

IQueryParser::P arse 方法分析用户输入字符串,并采用 IQuerySolution 的形式生成解释。 如果该方法的 pCustomProperties 参数不为 null,则它是 IRichChunk 对象的枚举(每个已识别的自定义属性的一个)。 其他 IQueryParser 方法允许应用程序为各种类型的命名实体设置多个选项,例如区域设置、架构、断字符和处理程序。 IQueryParser::GetSchemaProvider 返回用于浏览已加载架构的 ISchemaProvider 接口。

IQuerySolution : IConditionFactory

IQuerySolution 接口提供有关分析输入字符串结果的所有信息。 由于 IQuerySolution 也是 IConditionFactory 接口,因此可以创建其他条件树节点。 IQuerySolution::GetQuery 方法生成用于解释的条件树。 IQuerySolution::GetQuery 也返回语义类型。

IConditionFactory

IConditionFactory 创建条件树节点。 如果 IConditionFactory::MakeNot简化 参数为 VARIANT_TRUE,则生成的 ICondition 将会被简化,并且不一定是一个否定节点。 如果 IConditionFactory::MakeAndOrpSubConditions 参数不为 null,则该参数应为 ICondition 对象的枚举,并成为子树。IConditionFactory::MakeLeaf 使用指定的属性名称、作和值构造叶节点。 pValueType 参数中的字符串应是架构中的语义类型的名称。 如果 expand 参数是 VARIANT_TRUE 且属性是虚拟的,则生成的条件树通常是通过将属性扩展为其定义的组成部分而形成的析取。 如果不是 null,pPropertyNameTermpOperatorTermpValueTerm 参数应标识指示属性、作和值的术语。

ICondition : IPersistStream

ICondition 接口是条件树中的单个节点。 节点可以是否定节点、AND 节点、或节点,也可以是叶节点。 对于非叶节点 ICondition::GetSubConditions ,返回子树的枚举。 对于叶节点, ICondition 的以下方法返回以下值:

IRichChunk

每个 IRichChunk 对象标识一个令牌范围和一个字符串。 IRichChunk 是一个工具接口,用于表示由起始位置和长度确定的跨度(通常是标记范围)的信息。 此范围信息包括字符串和/或 VARIANT

IConditionGenerator

IConditionGenerator 接口由应用程序提供,用于处理命名实体类型的识别和条件树生成。 通过 IQueryParser::SetMultiOptionIQueryParser 提供条件生成器。 IQueryParser 使用 ISchemaProvider 为当前加载的架构调用 IConditionGenerator::Initialize 。 这样做允许 IConditionGenerator 获取所需的任何架构信息。 分析输入字符串时,IQueryParser 调用每个 IConditionGenerator 的 IConditionGenerator::RecognizeNamedEntities 方法,以便可以报告它在输入字符串中识别的命名实体的出现。 IQueryParser 可以使用当前区域设置,并应使用输入的标记化,因为它需要报告任何命名实体的令牌范围。

IQueryParser 即将发出叶节点,并且值的语义类型与 IConditionGenerator 的命名实体类型匹配时, IQueryParser 调用 IConditionGenerator::GenerateforLeaf ,其中包含要生成的节点的信息。 如果 IConditionGenerator 返回 S_OK,它应返回一个条件树(这不必是叶节点),并通知 IQueryParser 是否抑制它通常生成为预防措施的替代字符串解释。

ITokenCollection

ITokenCollection::NumberOfTokens 方法返回令牌数。ITokenCollection::GetToken 返回有关第 i个令牌的信息。 开头和长度是输入字符串中的字符位置。 仅当有文本覆盖输入字符串时,返回的文本才会为非 null。 例如,当该短划线位于应解释为否定的上下文中时,将其替换为“NOT”,以覆盖输入字符串中的短划线。

INamedEntityCollector

IConditionGenerator 为它识别的每个命名实体调用 INamedEntityCollector::Add 。 范围是标识符范围。 必须始终满足 beginSpan 的条件吗? beginActual<endActualendSpanbeginSpanendSpan 可能与 beginActualendActual 不同, 如果命名实体以语义上微不足道的标记(例如引号)开始和/或结束,但这些标记仍被命名实体所覆盖。 该值必须表示为字符串,随后将显示在对 IConditionGenerator::GenerateForLeaf 的调用中。

ISchemaProvider

ISchemaProvider 接口可用于浏览实体(类型)和关系(属性)的加载架构。 下面是各个方法的作用:

IEntity

IEntity 接口是一个架构实体,表示具有名称的类型、与其他类型(属性)的命名关系以及派生自基实体。 下面是各个方法的作用:

IRelationship

IRelationship 接口表示两个实体之间的关系:源和目标。 下面是各个方法的作用:

  • IRelationship::IsReal 报告关系是否真实。 例如,如果实体 A 派生自实体 B 并从中继承名为 R 的关系,A 可能仍有自己的名为 R 的关系。但是,A 和 R 之间的关系必须与 B 的目标类型相同,并且唯一存在的原因是存储特定于 B 的元数据。据说B的这种关系不是真的。
  • IRelationship::Metadata 返回一组 IMetaData 接口,每个接口对应于此实体的一个元数据对。
  • IRelationship::D efaultPhrase 返回在重述中用于此关系的默认短语。 每个关系都有一个默认短语,表示它有助于生成条件树的 AQS 或 NQS 重述。

IMetaData

元数据是键值对,每个键值对都与实体、关系或整个架构相关联。 由于键不一定是唯一的,因此可以将元数据集合视为多映射。 调用 IMetaData::GetData 来检索元数据对的键和值。

查询场景

以下方案描述了在常见的查询方案中在 Windows 搜索中使用结构化查询 API,例如创建条件树和查询索引。

条件提取和查询分析

创建查询时,通过告诉系统要搜索的位置来定义其范围。 这会限制搜索结果。 定义范围后,应用筛选器,并返回筛选器集。 搜索结果受限于使用叶节点生成条件树,类似于图形。 然后提取这些条件。 条件树是一个由叶条件通过布尔运算(与、或、非)组合而成的结构,其中每个叶条件通过一个运算将属性和一个值关联起来。 叶节点表示通过某些操作将单个属性限制到一个值。

筛选器限制需要描述限制的逻辑表达式。 定义此表达式以 ICondition 接口开头,该接口用于在条件树中创建单个节点。 由于以下示例中只有一个条件,因此树不会更改。

    
    [
        object,
        uuid(0FC988D4-C935-4b97-A973-46282EA175C8),
        pointer_default(unique)
    ]
    interface ICondition : IPersistStream
    {
        HRESULT GetConditionType([out, retval] CONDITION_TYPE* pNodeType);
        HRESULT GetSubConditions([in] REFIID riid, [out, retval, iid_is(riid)] void** ppv);
        [local] HRESULT GetComparisonInfo([out, annotation("__deref_opt_out")] LPWSTR *ppszPropertyName, [out, annotation("__out_opt")] CONDITION_OPERATION *pOperation, [out, annotation("__out_opt")] PROPVARIANT *pValue);
        HRESULT GetValueType([out, retval] LPWSTR* ppszValueTypeName);
        HRESULT GetValueNormalization([out, retval] LPWSTR* ppszNormalization);
        [local] HRESULT GetInputTerms([out, annotation("__out_opt")] IRichChunk** ppPropertyTerm, [out, annotation("__out_opt")] IRichChunk** ppOperationTerm, [out, annotation("__out_opt")] IRichChunk** ppValueTerm);
        HRESULT Clone([out, retval] ICondition** ppc);
    };


如果有多个筛选器条件,则 AND 和其他布尔运算符用于实现单个树。 AND 树和 OR 树表示子树的结合和分解。 NOT 树表示其单个子树的求反。 AQS 提供了一种文本方法来使用布尔运算符实现逻辑表达式,并且通常更简单。

在下一个示例中,我们将条件树(ICondition)转换为可视形式。 查询分析器使用 IQueryParser 接口将 ICondition 转换为格式为 RTF 的富文本查询字符串。 IQueryParser::RestateToString 方法返回查询文本,而 IQueryParser::P arse 方法生成 IQuerySolution 接口。 以下示例演示如何执行所有这些。

    [
        object,
        uuid(2EBDEE67-3505-43f8-9946-EA44ABC8E5B0),
        pointer_default(unique)
    ]
    interface IQueryParser : IUnknown
    {
        HRESULT Parse([in] LPCWSTR pszInputString, [in] IEnumUnknown* pCustomProperties, [out, retval] IQuerySolution** ppSolution);
        HRESULT SetOption([in] STRUCTURED_QUERY_SINGLE_OPTION option, [in] PROPVARIANT const* pOptionValue);
        HRESULT GetOption([in] STRUCTURED_QUERY_SINGLE_OPTION option, [out, retval] PROPVARIANT* pOptionValue);
        HRESULT SetMultiOption([in] STRUCTURED_QUERY_MULTIOPTION option, [in] LPCWSTR pszOptionKey, [in] PROPVARIANT const* pOptionValue);
        HRESULT GetSchemaProvider([out, retval] ISchemaProvider** ppSchemaProvider);
        HRESULT RestateToString([in] ICondition* pCondition, [in] BOOL fUseEnglish, [out] LPWSTR* ppszQueryString);
        HRESULT ParsePropertyValue([in] LPCWSTR pszPropertyName, [in] LPCWSTR pszInputString, [out, retval] IQuerySolution** ppSolution);
        HRESULT RestatePropertyValueToString([in] ICondition* pCondition, [in] BOOL fUseEnglish, [out] LPWSTR* ppszPropertyName, [out] LPWSTR* ppszQueryString);
    };

IQueryParser::Parse 的主要输入是要解析的用户字符串输入,但应用程序还可以通知查询分析器其识别的任何输入属性(基于特定于应用程序的语法)。 IQueryParser::Parse 的输出是 IQuerySolution,它提供与该解析调用相关的所有信息。 有一些方法可用于获取输入字符串、输入字符串的标记化方式、任何分析错误,以及分析的查询作为条件树,由 ICondition 表示。 以下示例显示...

    [
        object,
        uuid(D6EBC66B-8921-4193-AFDD-A1789FB7FF57),
        pointer_default(unique)
    ]
    interface IQuerySolution : IConditionFactory
    {
        [local] HRESULT GetQuery([out, annotation("__out_opt")] ICondition** ppQueryNode, [out, annotation("__out_opt")] IEntity** ppMainType);
        HRESULT GetErrors([in] REFIID riid, [out, retval, iid_is(riid)] void** ppParseErrors);
        [local] HRESULT GetLexicalData([out, annotation("__deref_opt_out")] LPWSTR* ppszInputString, [out, annotation("__out_opt")] ITokenCollection** ppTokens, [out, annotation("__out_opt")] LCID* pLocale, [out, annotation("__out_opt")] IUnknown** ppWordBreaker);
    }    

    

在前面的示例中, IQuerySolution::GetQuery 可以获取有关查询的任何信息,包括原始文本、构成文本的标记或条件树。 下表列出了可能返回的查询值的示例。

返回的查询值示例 DESCRIPTION
author:relja OR author:tyler IQueryParser::RestateToString 返回的查询文本
?author?, ?:?, ?relja?, ?OR?, ?author?, ?:?, ?tyler? 令牌分解
未解析的条件树 未解析的条件树

 

返回的初始条件树未解决。 在未解析的条件树中,日期和时间引用(例如 date:yesterday)不会转换为绝对时间。 此外,不会扩展虚拟属性。 虚拟属性是充当多个属性聚合的属性。

例如,查询 kind:email from:reljai 生成以下未解析和已解析的条件树。 未解析的条件树位于左侧,解析的条件树位于右侧。

未解析和已解决的条件树

可以通过调用 IConditionFactory::Resolve 来获取解析树。 但是,传递 SQRO_DONT_RESOLVE_DATETIME 会使日期和时间保持未解析。 未解析的条件树有优点,因为未解析的条件树包含有关查询的信息。 每个叶节点指向由 IQuerySolution::GetLexicalData 返回的令牌,这些令牌在使用 IRichChunk 接口时对应于属性、运算符和值。 以下示例显示...

    interface ITokenCollection : IUnknown
    {
        HRESULT NumberOfTokens(ULONG* pCount);
        HRESULT GetToken([in] ULONG i, [out, annotation("__out_opt")] ULONG* pBegin, [out, annotation("__out_opt")] ULONG* pLength, [out, annotation("__deref_opt_out")] LPWSTR* ppsz);
    };

ICondition:: GetInputTerms([out, annotation("__out_opt")] 
IRichChunk** ppPropertyTerm, [out, annotation("__out_opt")] 
IRichChunk** ppOperationTerm, [out, annotation("__out_opt")] 
IRichChunk** ppValueTerm);

    interface IRichChunk : IUnknown
    {
        HRESULT GetData([out, annotation("__out_opt")] ULONG* pFirstPos, [out, annotation("__out_opt")] ULONG* pLength, [out, annotation("__deref_opt_out")] LPWSTR* ppsz, [out, annotation("__out_opt")] PROPVARIANT* pValue);
    }

查询索引

查询索引的方法有多种。 有些基于 SQL,而另一些则基于 AQS。 还可以使用 查询接口以编程方式查询 Windows 搜索索引。 有三个特定于查询索引的接口: ISearchQueryHelperIRowsetPrioritizationIRowsetEvents。 有关概念性信息,请参阅 以编程方式查询索引

可以使用 ISearchQueryHelper 接口开发组件或帮助程序类来查询索引。 此接口作为 ISearchCatalogManager (和 ISearchCatalogManager2)的帮助程序类实现,并通过调用 ISearchCatalogManager::GetQueryHelper 获取。 有关概念性信息,请参阅 使用 ISearchQueryHelper 查询索引

ISearchQueryHelper 允许你:

  • 获取用于连接到 Windows 搜索数据库的 OLE DB 连接字符串。
  • 将 AQS 用户查询转换为 Windows 搜索 SQL。
  • 指定可在 SQL 中表示但不能在 AQS 中表示的查询限制。

Windows 7 及更高版本中支持索引优先级和行集事件。 通过 IRowsetPrioritization ,有一个优先级堆栈,使客户端能够请求特定查询中使用的范围高于正常优先级。 IRowsetEvents 提供对行集中项的更改通知,包括添加新项、删除项以及项数据的修改。 使用行集事件通知可确保现有查询的结果尽可能最新。 有关概念性信息,请参阅 Windows 7 中的索引优先级和行集事件

在 Windows 搜索 索引、查询和通知

索引 中包含的内容

Windows 搜索 中的 索引过程

Windows 搜索中的通知过程

URL 格式要求