Active Directory 支持虚拟列表视图 (VLV) 搜索。 此搜索样式专为大型结果集而设计,可使应用程序显示数千个条目的子集,而无需实际检索每个条目。
VLV 搜索有两种不同的使用方法。 第一种是根据数字偏移量来检索特定条目的属性。 这种方法在响应滚动操作检索搜索结果时非常有用。
使用 VLV 搜索的第二种方法是搜索部分或全部文本属性,并仅显示搜索结果。 通讯簿就是一个示例。 如果用户键入“s”,则应用程序就可以使用 VLV 搜索来搜索以“s”开头的公用名条目。 如果用户随后在“s”后面添加一个“m”,应用程序就可以使用另一个 VLV 搜索来搜索以“sm”开头的公用名条目。
要执行 VLV 搜索,请指示 ADSI 使用 VLV 控件。 为此,请使用 ADS_SEARCHPREF_VLV 搜索选项和 ADSTYPE_PROV_SPECIFIC 值来调用 IDirectorySearch::SetSearchPreference 方法。 ADSTYPE_PROV_SPECIFIC 值是指向 ADS_VLV 结构的指针,该结构包含了有关搜索的数据。 GetVLVItemCount 示例函数展示了如何设置这两种搜索首选项。
所有 VLV 搜索都必须使用服务器端结果排序,这可以通过设置 ADS_SEARCHPREF_SORT_ON 搜索首选项来执行。 有关 ADS_SEARCHPREF_SORT_ON 搜索首选项的更多信息,请参阅使用 IDirectorySearch 对搜索结果排序。
在执行 VLV 搜索时,将通过调用具有 ADS_VLV_RESPONSE 标识符的 IDirectorySearch::GetColumn 在列中返回有关搜索的一定数量的元数据。 该数据包含在 ADS_VLV 结构中。 特别重要的是 dwContentCount 和 lpContextID 成员。 dwContentCount 成员将包含符合 VLV 搜索条件的结果数量。 此值可用于估算该类型搜索返回的项目总数。 lpContextID 成员包含一个服务器定义的值,该值可传递给下一次搜索, 使用 lpContextID 可以增强搜索性能。 请注意,lpContextID 是服务器定义的值,其长度包含在 dwContextIDLength 成员中。 在调用 IDirectorySearch::FreeColumn 方法时会释放该缓冲区,因此调用方必须分配一个适当大小的缓冲区,并在两次搜索之间复制和保存缓冲区的内容。
有关 LDAP VLV 控制的更多信息,请参阅使用 LDAP VLV 控件进行搜索。
有关详细信息,请参阅:
- 获取项目数
- 按偏移量搜索
- 按字符串搜索
- 使用 VLV 搜索的示例代码
获取项目数
要估算特定搜索将返回的项目数,请执行以下步骤。
用所有零值或 NULL 值填充 ADS_VLV 结构。
在 ADS_SEARCHPREF_INFO 中填写以下值。
填写 ADS_SORTKEY 结构,如使用 IDirectorySearch 对搜索结果排序中所示,以便根据所需属性进行排序。
填写另一个 ADS_SEARCHPREF_INFO 将 ADS_SORTKEY 结构添加到搜索首选项中,如使用 IDirectorySearch 对搜索结果排序中所示。
添加任何其他所需的搜索首选项,并调用 IDirectorySearch::SetSearchPreference 以设置搜索首选项。
使用 IDirectorySearch::ExecuteSearch 执行搜索。
通过调用 IDirectorySearch::GetFirstRow 来获取第一行结果。
使用 ADS_VLV_RESPONSE 来调用 IDirectorySearch::GetColumn,以获取 VLV 搜索元数据。
将 ADS_SEARCH_COLUMN 结构的 pADsValues->ProviderSpecific.lpValue 转换为 ADS_VLV 结构指针。 此 ADS_VLV 结构的 dwContentCount 成员包含该类型搜索将返回的项目的大致数量。
如果要执行同类型的其他 VLV 搜索,请复制 lpContextID 数据并保存,以备下一次 VLV 搜索使用。
GetVLVItemCount 示例函数演示了如何执行此操作。
按偏移量搜索
VLV 搜索之所以如此快速,是因为可以通过数字偏移量来搜索特定结果。 例如,如果一次搜索会返回 10,000 个项目,那么 VLV 搜索就可以获取大约第 4072 个项目的信息,而无需检索该项目之前的所有项目。
偏移量是以偏移量与内容计数的比率来指定的。 比率之所以有用,是因为服务器可能无法准确估计列表中存在的条目数量,或者列表大小可能会在用户浏览列表期间发生变化。 由于必须指明列表的开始和结束,因此可以在第一个搜索请求中使用内容计数的估计值以及偏移值。 服务器根据其对内容计数的理解,使用这些数据计算出列表中的相应偏移量,并通过 ADS_VLV 结构中的 dwContentCount 成员发送给客户端。 例如,如果估计列表大小为 3000,并希望偏移量为列表条目 1500,则应将 dwContentCount 设置为 3000,并将 dwOffset 设置为 1500。 如果服务器估计实际列表大小为 4500,则会将偏移量重新计算为 2250,并在 dwContentCount 和 dwOffset 中返回新的估计值。
注意
VLV 搜索中的所有数值都是近似值,不应作为绝对值使用。 例如,如果对 100 个定量中的第 50 个项目发出 VLV 搜索,则并不能保证得到准确的中间项目。
要按偏移量搜索特定项目,请执行以下步骤。
在 ADS_VLV 结构中填写以下值。 结构中的其他成员应设置为零或 NULL。
- 将 dwContentCount 成员设置为要检索项目比例的最大值。
- 将 dwOffset 成员设置为要检索的一个或多个项目相对于 dwContentCount 的比率。
- 将 lpContextID 成员设置为上下文 ID 缓冲区副本的地址,并将 dwContextIDLength 设置为上下文 ID 缓冲区的长度(以字节为单位)。 如果未保存任何上下文 ID,则这两个成员都应为零或 NULL。
设置搜索首选项,如“获取项数”过程的步骤 2 到步骤 5 中所示。
使用 IDirectorySearch::ExecuteSearch 执行搜索。
通过调用 IDirectorySearch::GetFirstRow 来获取第一行结果。
使用要检索的属性名称调用 IDirectorySearch::GetColumn 以获取所请求项目的实际数据。
使用 ADS_VLV_RESPONSE 来调用 IDirectorySearch::GetColumn,以获取 VLV 搜索元数据。
将 ADS_SEARCH_COLUMN 结构的 pADsValues->ProviderSpecific.lpValue 转换为 ADS_VLV 结构指针。
复制 lpContextID 数据并保存,以备下一次 VLV 搜索使用。
GetVLVItemText 示例函数演示了如何执行此操作。
还可以通过单次搜索调用来检索多行数据。 为此,可在步骤 1 中适当设置 ADS_VLV 结构的 dwBeforeCount 和 dwAfterCount 成员。 dwBeforeCount 成员包含在相关项目之前出现在列表中的项目数,而 dwAfterCount 成员包含在相关项目之后出现在列表中的项目数。 这两个计数都不包括项目本身,因此将 dwBeforeCount 设置为 10 和 dwAfterCount 设置为 10 将总共返回 21 个项目。 此选项可在客户端缓存搜索结果。
按字符串搜索
还可以使用 VLV 搜索来查找具有字符串属性的项目,该属性的值与字符串的全部或部分匹配,而无需检索所有项目。 字符串匹配是针对 ADS_SEARCHPREF_SORT_ON 搜索首选项的 ADS_SORTKEY 结构中指定的属性进行的。
要按字符串搜索特定项目,请执行以下步骤。
在 ADS_VLV 结构中填写以下值。 结构中的其他成员应设置为零或 NULL。
- 将 pszTarget 成员设置为指向以 NULL 结尾的字符串的指针,该字符串包含要搜索的字符串。
- 将 lpContextID 成员设置为上下文 ID 缓冲区副本的地址,并将 dwContextIDLength 设置为上下文 ID 缓冲区的长度(以字节为单位)。 如果未保存任何上下文 ID,则这两个成员都应为零或 NULL。
设置搜索首选项,如“获取项数”过程的步骤 2 到步骤 5 中所示。
使用 IDirectorySearch::ExecuteSearch 执行搜索。
通过调用 IDirectorySearch::GetFirstRow 来获取第一行结果。
使用要检索的属性名称调用 IDirectorySearch::GetColumn 以获取所请求项目的实际数据。
使用 ADS_VLV_RESPONSE 来调用 IDirectorySearch::GetColumn,以获取 VLV 搜索元数据。
将 ADS_SEARCH_COLUMN 结构的 pADsValues->ProviderSpecific.lpValue 转换为 ADS_VLV 结构指针。
复制 lpContextID 数据并保存,以备下一次 VLV 搜索使用。 如果需要,dwOffset 成员包含字符串属性以 pszTarget中指定的值开头的第一个项目的单索引。
GetVLVItemsByString 示例函数演示了如何执行此操作。
与通过索引搜索类似,也可以通过单次搜索调用来检索多行数据。 这同样是通过适当设置 ADS_VLV 结构的 dwBeforeCount 和 dwAfterCount 成员来实现的。