如何使用 VLV 进行搜索

Active Directory 支持虚拟列表视图 (VLV) 搜索。 此搜索样式专为大型结果集而设计,使应用程序能够显示数千个条目的子集,而无需实际检索每个条目。

可以使用两种不同的方式使用 VLV 搜索。 第一个是基于数值偏移量检索特定条目的属性。 此方法在检索搜索结果以响应滚动操作时非常有用。

使用 VLV 搜索的第二种方法是搜索部分或全部文本属性,并仅显示搜索结果。 这是通讯簿的示例用法。 如果用户键入“s”,则应用程序可以使用 VLV 搜索搜索以“s”开头的公用名条目。 如果用户随后将“m”添加到“s”,则应用程序可以使用另一个 VLV 搜索搜索以“sm”开头的公用名条目。

若要执行 VLV 搜索,请指示 ADSI 使用 VLV 控件。 为此,请使用具有ADSTYPE_PROV_SPECIFIC值的ADS_SEARCHPREF_VLV搜索选项调用 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 结构中。 特别重要的是 dwContentCountlpContextID 成员。 dwContentCount 成员将包含满足 VLV 搜索条件的结果数。 此值可用作为搜索该类型返回的项总数的估计值。 lpContextID 成员包含一个服务器定义的值,该值可以传递给下一个搜索来标识搜索。 使用 lpContextID 可以增强搜索性能。 请注意 ,lpContextID 是服务器定义值,其长度包含在 dwContextIDLength 成员中。 调用 IDirectorySearch::FreeColumn 方法时释放此缓冲区,因此调用方必须在搜索之间分配适当大小的缓冲区并复制并保存缓冲区的内容。

有关 LDAP VLV 控件的详细信息,请参阅 使用 LDAP VLV 控件进行搜索

有关详细信息,请参阅:

获取项数

若要获取特定搜索将返回的项数的估计值,请执行以下步骤。

  1. 使用所有零或 NULL 值填充ADS_VLV结构。

  2. 使用以下值填充 ADS_SEARCHPREF_INFO

    • dwSearchPref 成员设置为 ADS_SEARCHPREF_VLV
    • vValue.dwType 成员设置为 ADSTYPE_PROV_SPECIFIC
    • vValue.ProviderSpecific.dwLength 成员设置为 ADS_VLV 结构的大小。
    • vValue.ProviderSpecific.lpValue 成员设置为步骤 1 中ADS_VLV 结构的地址。
  3. 填充 ADS_SORTKEY 结构,如 使用 IDirectorySearch 对搜索结果进行排序 以对所需属性进行排序。

  4. 填充另一 个ADS_SEARCHPREF_INFO ,将 ADS_SORTKEY 结构添加到搜索首选项,如 使用 IDirectorySearch 对搜索结果进行排序所示。

  5. 添加任何其他所需的搜索首选项并调用 IDirectorySearch::SetSearchPreference 以设置搜索首选项。

  6. 使用 IDirectorySearch::ExecuteSearch 执行搜索。

  7. 通过调用 IDirectorySearch::GetFirstRow 获取结果的第一行。

  8. 使用 ADS_VLV_RESPONSE 调用 IDirectorySearch::GetColumn 以获取 VLV 搜索元数据。

  9. ADS_SEARCH_COLUMN结构的 pADsValues-ProviderSpecific.lpValue> 强制转换为ADS_VLV结构指针。 此ADS_VLV结构的 dwContentCount 成员包含搜索该类型的近似项数。

  10. 如果执行同一类型的其他 VLV 搜索,请创建 lpContextID 数据的副本,并将其保留为下一个 VLV 搜索。

GetVLVItemCount 示例函数演示如何执行此操作。

按偏移量搜索

使 VLV 搜索如此快速的一件事是,可以通过数字偏移量搜索特定结果。 例如,如果搜索结果将返回 10,000 个项目,则 VLV 搜索可以获取大约 4072 项的信息,而无需检索有关项之前的所有项。

偏移量指定为偏移量与内容计数之间的比率。 比率非常有用,因为服务器可能无法准确估计列表中存在的条目数,或者用户在浏览列表时可能会更改列表大小。 由于必须指示列表的开始和结尾,因此可以在第一个搜索请求中使用内容计数的估计值,以及偏移值。 服务器使用此数据根据列表内的内容计数概念计算相应的偏移量,该偏移量通过ADS_VLV结构的 dwContentCount 成员发送到客户端。 例如,如果估计列表大小为 3000,并且希望偏移量为列表条目 1500,则会将 dwContentCount 设置为 3000, dwOffset 设置为 1500。 如果服务器估计实际列表大小为 4500,它将重新计算到 2250 的偏移量,并返回 dwContentCountdwOffset 中的新估计值。

注意

VLV 搜索中的所有数值都是近似值,不应用于绝对值。 例如,如果在配给为 100 的配给中发出第 50 个项目的 VLV 搜索,则不能保证获得确切的中间项。

若要按偏移量搜索特定项,请执行以下步骤。

  1. 使用以下值填充 ADS_VLV 结构。 结构的其他成员应设置为零或 NULL

    • dwContentCount 成员设置为要检索的项比率的最大值。
    • dwOffset 成员设置为要检索的项或项的比率(相对于 dwContentCount)。
    • lpContextID 成员设置为上下文 ID 缓冲区副本的地址,并将 dwContextIDLength 设置为上下文 ID 缓冲区的长度(以字节为单位)。 如果未保存任何上下文 ID,则这两个成员都应为零或 NULL
  2. 设置搜索首选项,如“获取项数”过程的步骤 2 到步骤 5 所示。

  3. 使用 IDirectorySearch::ExecuteSearch 执行搜索。

  4. 通过调用 IDirectorySearch::GetFirstRow 获取结果的第一行。

  5. 使用要检索的属性的名称调用 IDirectorySearch::GetColumn 以获取请求项的实际数据。

  6. 使用 ADS_VLV_RESPONSE 调用 IDirectorySearch::GetColumn 以获取 VLV 搜索元数据。

  7. ADS_SEARCH_COLUMN结构的 pADsValues-ProviderSpecific.lpValue> 强制转换为ADS_VLV结构指针。

  8. 创建 lpContextID 数据的副本,并将其保留为下一个 VLV 搜索。

 

GetVLVItemText 示例函数演示如何执行此操作。

还可以使用单个搜索调用检索多个数据行。 这是在步骤 1 中完成的,方法是适当地设置ADS_VLV结构的 dwBeforeCountdwAfterCount 成员。 dwBeforeCount 成员包含在该项目中之前在列表中显示的项目数,dwAfterCount 成员包含在该列表中出现的项数,这些项将出现在有关项之后的列表中。 这两个计数都排除了项本身,因此将 dwBeforeCount 设置为 10, dwAfterCount 设置为 10 将导致总共返回 21 个项目。 此选项允许在客户端缓存搜索结果。

按字符串搜索

还可以使用 VLV 搜索查找具有字符串属性的项,其值与字符串的所有或部分匹配,而无需检索所有项。 字符串匹配针对ADS_SEARCHPREF_SORT_ON搜索首选项ADS_SORTKEY结构中指定的属性执行。

若要按字符串搜索特定项,请执行以下步骤。

  1. 使用以下值填充 ADS_VLV 结构。 结构的其他成员应设置为零或 NULL

    • pszTarget 成员设置为指向包含要搜索的字符串的 NULL 终止字符串的指针。
    • lpContextID 成员设置为上下文 ID 缓冲区副本的地址,并将 dwContextIDLength 设置为上下文 ID 缓冲区的长度(以字节为单位)。 如果未保存任何上下文 ID,则这两个成员都应为零或 NULL
  2. 设置搜索首选项,如“获取项数”过程的步骤 2 到步骤 5 所示。

  3. 使用 IDirectorySearch::ExecuteSearch 执行搜索。

  4. 通过调用 IDirectorySearch::GetFirstRow 获取结果的第一行。

  5. 使用要检索的属性的名称调用 IDirectorySearch::GetColumn 以获取请求项的实际数据。

  6. 使用 ADS_VLV_RESPONSE 调用 IDirectorySearch::GetColumn 以获取 VLV 搜索元数据。

  7. ADS_SEARCH_COLUMN结构的 pADsValues-ProviderSpecific.lpValue> 强制转换为ADS_VLV结构指针。

  8. 创建 lpContextID 数据的副本,并将其保留为下一个 VLV 搜索。 如果需要, dwOffset 成员包含其字符串属性以 pszTarget 中指定的值开头的第一项的一个基于索引的索引。

GetVLVItemsByString 示例函数演示如何执行此操作。

与按索引搜索类似,还可以使用单个搜索调用检索多个数据行。 这可以通过适当地设置ADS_VLV结构的 dwBeforeCountdwAfterCount 成员来实现。