Chapter 4. Using virtual list view control to request a contiguous subset of a large search result Directory Server supports the LDAP virtual list view control. This control enables an LDAP client to request a contiguous subset of a large search result. For example, you have stored an address book with 100.000 entries in Directory Server. By default, a query for all entries returns all entries at once. This is a resource and time-consuming operation, and clients often do not require the whole data set because, if the user scrolls through the results, only a partial set is visible. However, if the client uses the VLV control, the server only returns a subset and, for example, if the user scrolls in the client application, the server returns more entries. This reduces the load on the server, and the client does not need to store and process all data at once. VLV also improves the performance of server-sorted searches when all search parameters are fixed. Directory Server pre-computes the search results within the VLV index. Therefore, the VLV index is much more efficient than retrieving the results and sorting them afterwards. In Directory Server, the VLV control is always available. However, if you use it in a large directory, a VLV index, also called browsing index, can significantly improve the speed. Directory Server does not maintain VLV indexes for attributes, such as for standard indexes. The server generates VLV indexes dynamically based on attributes set in entries and the location of those entries in the directory tree. Unlike standard entries, VLV entries are special entries in the database. 4.1. How the VLV control works in ldapsearch commands Typically, you use the virtual list view (VLV) feature in LDAP client applications. However, for example for testing purposes, you can use the ldapsearch utility to request only partial results. To use the VLV feature in ldapsearch commands, specify the -E option for both the sss (server-side sorting) and vlv search extensions: # ldapsearch ... -E 'sss= attribute_list ' -E 'vlv= query_options ' The sss search extension has the following syntax: [!]sss=[-]<attr[:OID]>[/[-]<attr[:OID]>...] The vlv search extension has the following syntax: [!]vlv=<before>/<after>(/<offset>/<count>|:<value>) before sets the number of entries returned before the targeted one. after sets the number of entries returned after the targeted one. index , count , and value help to determine the target entry. If you set value , the target entry is the first one having its first sorting attribute starting with the value. Otherwise, you set count to 0 , and the target entry is determined by the index value (starting from 1). If the count value is higher than 0 , the target entry is determined by the ratio index * number of entries / count . Example 4.1. Output of an ldapsearch command with VLV search extension The following command searches in ou=People,dc=example,dc=com . The server then sorts the results by the cn attribute and returns the uid attributes of the 70th entry together with one entry before and two entries after the offset. # ldapsearch -D " cn=Directory Manager " -W -H ldap://server.example.com -b "ou=People,dc=example,dc=com" -s one -x -E 'sss=cn' -E 'vlv=1/2/70/0' uid # user069, People, example.com dn: uid=user069,ou=People,dc=example,dc=com uid: user069 # user070, People, example.com dn: uid=user070,ou=People,dc=example,dc=com uid: user070 # user071, People, example.com dn: uid=user071,ou=People,dc=example,dc=com uid: user071 # user072, People, example.com dn: uid=user072,ou=People,dc=example,dc=com uid: user072 # search result search: 2 result: 0 Success control: 1.2.840.113556.1.4.474 false MIQAAAADCgEA sortResult: (0) Success control: 2.16.840.1.113730.3.4.10 false MIQAAAALAgFGAgMAnaQKAQA= vlvResult: pos=70 count=40356 context= (0) Success # numResponses: 5 # numEntries: 4 Press [before/after(/offset/count|:value)] Enter for the window. Additional resources The -E parameter description in the ldapsearch(1) man page. 4.2. Enabling unauthenticated users to use the VLV control By default, the access control instruction (ACI) in the oid=2.16.840.1.113730.3.4.9,cn=features,cn=config entry enables only authenticated users to use the VLV control. To enable also non-authenticated users to use the VLV control, update the ACI by changing userdn = "ldap:///all" to userdn = "ldap:///anyone" Procedure Update the ACI in oid=2.16.840.1.113730.3.4.9,cn=features,cn=config : # ldapmodify -D " cn=Directory Manager " -W -H ldap://server.example.com -x dn: oid=2.16.840.1.113730.3.4.9,cn=features,cn=config changetype: modify replace: aci aci: (targetattr != "aci")(version 3.0; acl "VLV Request Control"; allow( read, search, compare, proxy ) userdn = "ldap:///anyone";) Verification Perform a query with VLV control not specify a bind user: # ldapsearch -H ldap://server.example.com -b " ou=People,dc=example,dc=com " -s one -x -E 'sss= cn ' -E 'vlv= 1/2/70/0 ' uid This command requires that the server allows anonymous binds. If the command succeeds but returns no entries, run the query again with a bind user to ensure that the query works when using authentication. Additional resources Disabling anonymous binds 4.3. Creating a VLV index using the command line to improve the speed of VLV queries Follow this procedure to create a virtual list view (VLV) index, also called browsing index, for entries in ou=People,dc=example,dc=com that contain a mail attribute and have the objectClass attribute set to person . Prerequisites Your client applications use the VLV control. Client applications require to query a contiguous subset of a large search result. The directory contains a large number of entries. Procedure Create the VLV search entry: # dsconf -D " cn=Directory Manager " ldap://server.example.com backend vlv-index add-search --name " VLV People " --search-base " ou=People,dc=example,dc=com " --search-filter " (&(objectClass=person)(mail=*)) " --search-scope 2 userRoot This command uses the following options: --name sets the name of the search entry. This can be any name. --search-base sets the base DN for the VLV index. Directory Server creates the VLV index on this entry. --search-scope sets the scope of the search to run for entries in the VLV index. You can set this option to 0 (base search), 1 (one-level search), or 2 (subtree search). --search-filter sets the filter Directory Server applies when it creates the VLV index. Only entries that match this filter become part of the index. userRoot is the name of the database in which to create the entry. Create the index entry: # dsconf -D " cn=Directory Manager " ldap://server.example.com backend vlv-index add-index --index-name " VLV People - cn sn " --parent-name " VLV People " --sort " cn sn " --index-it userRoot This command uses the following options: --index-name sets the name of the index entry. This can be any name. --parent-name sets the name of the VLV search entry and must match the name you set in the step. --sort sets the attribute names and their sort order. Separate the attributes by space. --index-it causes that Directory Server automatically starts an index task after the entry was created. userRoot is the name of the database in which to create the entry. Verification Verify the successful creation of the VLV index in the /var/log/dirsrv/slapd- instance_name /errors file: [26/Nov/2021:11:32:59.001988040 +0100] - INFO - bdb_db2index - userroot: Indexing VLV: VLV People - cn sn [26/Nov/2021:11:32:59.507092414 +0100] - INFO - bdb_db2index - userroot: Indexed 1000 entries (2%). ... [26/Nov/2021:11:33:21.450916820 +0100] - INFO - bdb_db2index - userroot: Indexed 40000 entries (98%). [26/Nov/2021:11:33:21.671564324 +0100] - INFO - bdb_db2index - userroot: Finished indexing. Use the VLV control in an ldapsearch command to query only specific records from the directory: # ldapsearch -D " cn=Directory Manager " -W -H ldap://server.example.com -b "ou=People,dc=example,dc=com" -s one -x -E 'sss=cn' -E 'vlv=1/2/70/0' uid # user069, People, example.com dn: uid=user069,ou=People,dc=example,dc=com cn: user069 # user070, People, example.com dn: uid=user070,ou=People,dc=example,dc=com cn: user070 # user071, People, example.com dn: uid=user071,ou=People,dc=example,dc=com cn: user071 # user072, People, example.com dn: uid=user072,ou=People,dc=example,dc=com cn: user072 This example assumes you have entries continuously named uid=user001 to at least uid=user072 in ou=People,dc=example,dc=com . Additional resources The -E parameter description in the ldapsearch(1) man page. The VLV control in ldapsearch commands 4.4. Creating a VLV index using the web console to improve the speed of VLV queries Follow this procedure to create a virtual list view (VLV) index, also called browsing index, for entries in ou=People,dc=example,dc=com that contain a mail attribute and have the objectClass attribute set to person . Prerequisites You are logged in to the instance in the web console. Your client applications use the VLV control. Client applications require to query a contiguous subset of a large search result. The directory contains a large number of entries. Procedure Navigate to Database Suffixes dc=example,dc=com VLV Indexes . Click Create VLV Index , and fill the fields: VLV Index Name : The name of the search entry. This can be any name. Search base : The base DN for the VLV index. Directory Server creates the VLV index on this entry. Search Filter : The filter Directory Server applies when it creates the VLV index. Only entries that match this filter become part of the index. Search Scope : The scope of the search to run for entries in the VLV index. Click Save VLV Index . Click Create Sort Index Enter the attribute names, and select Reindex After Saving . Click Create Sort Index . Verification Navigate to Monitoring Logging Errors Log and verify the successful creation of the VLV index: [26/Nov/2021:11:32:59.001988040 +0100] - INFO - bdb_db2index - userroot: Indexing VLV: VLV People - cn sn [26/Nov/2021:11:32:59.507092414 +0100] - INFO - bdb_db2index - userroot: Indexed 1000 entries (2%). ... [26/Nov/2021:11:33:21.450916820 +0100] - INFO - bdb_db2index - userroot: Indexed 40000 entries (98%). [26/Nov/2021:11:33:21.671564324 +0100] - INFO - bdb_db2index - userroot: Finished indexing. Use the VLV control in an ldapsearch command to query only specific records from the directory: # ldapsearch -D " cn=Directory Manager " -W -H ldap://server.example.com -b "ou=People,dc=example,dc=com" -s one -x -E 'sss=cn' -E 'vlv=1/2/70/0' uid # user069, People, example.com dn: uid=user069,ou=People,dc=example,dc=com cn: user069 # user070, People, example.com dn: uid=user070,ou=People,dc=example,dc=com cn: user070 # user071, People, example.com dn: uid=user071,ou=People,dc=example,dc=com cn: user071 # user072, People, example.com dn: uid=user072,ou=People,dc=example,dc=com cn: user072 This example assumes you have entries continuously named uid=user001 to at least uid=user072 in ou=People,dc=example,dc=com . Additional resources The -E parameter description in the ldapsearch(1) man page. The VLV control in ldapsearch commands

Commands:
ldapsearch ... -E 'sss= attribute_list ' -E 'vlv= query_options '
[!]sss=[-]<attr[:OID]>[/[-]<attr[:OID]>...]
[!]vlv=<before>/<after>(/<offset>/<count>|:<value>)
ldapsearch -D " cn=Directory Manager " -W -H ldap://server.example.com -b "ou=People,dc=example,dc=com" -s one -x -E 'sss=cn' -E 'vlv=1/2/70/0' uid user069, People, example.com dn: uid=user069,ou=People,dc=example,dc=com uid: user069 user070, People, example.com dn: uid=user070,ou=People,dc=example,dc=com uid: user070 user071, People, example.com dn: uid=user071,ou=People,dc=example,dc=com uid: user071 user072, People, example.com dn: uid=user072,ou=People,dc=example,dc=com uid: user072 search result search: 2 result: 0 Success control: 1.2.840.113556.1.4.474 false MIQAAAADCgEA sortResult: (0) Success control: 2.16.840.1.113730.3.4.10 false MIQAAAALAgFGAgMAnaQKAQA= vlvResult: pos=70 count=40356 context= (0) Success numResponses: 5 numEntries: 4 Press [before/after(/offset/count|:value)] Enter for the next window.
ldapmodify -D " cn=Directory Manager " -W -H ldap://server.example.com -x dn: oid=2.16.840.1.113730.3.4.9,cn=features,cn=config changetype: modify replace: aci aci: (targetattr != "aci")(version 3.0; acl "VLV Request Control"; allow( read, search, compare, proxy ) userdn = "ldap:///anyone";)
ldapsearch -H ldap://server.example.com -b " ou=People,dc=example,dc=com " -s one -x -E 'sss= cn ' -E 'vlv= 1/2/70/0 ' uid
dsconf -D " cn=Directory Manager " ldap://server.example.com backend vlv-index add-search --name " VLV People " --search-base " ou=People,dc=example,dc=com " --search-filter " (&(objectClass=person)(mail=*)) " --search-scope 2 userRoot
dsconf -D " cn=Directory Manager " ldap://server.example.com backend vlv-index add-index --index-name " VLV People - cn sn " --parent-name " VLV People " --sort " cn sn " --index-it userRoot
[26/Nov/2021:11:32:59.001988040 +0100] - INFO - bdb_db2index - userroot: Indexing VLV: VLV People - cn sn [26/Nov/2021:11:32:59.507092414 +0100] - INFO - bdb_db2index - userroot: Indexed 1000 entries (2%). [26/Nov/2021:11:33:21.450916820 +0100] - INFO - bdb_db2index - userroot: Indexed 40000 entries (98%). [26/Nov/2021:11:33:21.671564324 +0100] - INFO - bdb_db2index - userroot: Finished indexing.
ldapsearch -D " cn=Directory Manager " -W -H ldap://server.example.com -b "ou=People,dc=example,dc=com" -s one -x -E 'sss=cn' -E 'vlv=1/2/70/0' uid user069, People, example.com dn: uid=user069,ou=People,dc=example,dc=com cn: user069 user070, People, example.com dn: uid=user070,ou=People,dc=example,dc=com cn: user070 user071, People, example.com dn: uid=user071,ou=People,dc=example,dc=com cn: user071 user072, People, example.com dn: uid=user072,ou=People,dc=example,dc=com cn: user072
[26/Nov/2021:11:32:59.001988040 +0100] - INFO - bdb_db2index - userroot: Indexing VLV: VLV People - cn sn [26/Nov/2021:11:32:59.507092414 +0100] - INFO - bdb_db2index - userroot: Indexed 1000 entries (2%). [26/Nov/2021:11:33:21.450916820 +0100] - INFO - bdb_db2index - userroot: Indexed 40000 entries (98%). [26/Nov/2021:11:33:21.671564324 +0100] - INFO - bdb_db2index - userroot: Finished indexing.
ldapsearch -D " cn=Directory Manager " -W -H ldap://server.example.com -b "ou=People,dc=example,dc=com" -s one -x -E 'sss=cn' -E 'vlv=1/2/70/0' uid user069, People, example.com dn: uid=user069,ou=People,dc=example,dc=com cn: user069 user070, People, example.com dn: uid=user070,ou=People,dc=example,dc=com cn: user070 user071, People, example.com dn: uid=user071,ou=People,dc=example,dc=com cn: user071 user072, People, example.com dn: uid=user072,ou=People,dc=example,dc=com cn: user072