---
title: Query
description: Examples in this documentation depend on features activated in the ds-evaluation setup profile.
component: pingds
version: 8.1
page_id: pingds:rest-guide:query-rest
canonical_url: https://docs.pingidentity.com/pingds/8.1/rest-guide/query-rest.html
revdate: 2025-10-22T14:42:39Z
keywords: ["REST API"]
section_ids:
  example_query_filters: Example query filters
  build_query_filters: Build query filters
  query-rest-graph: Graph-like queries
  query-rest-complex: Queries and JSON attributes
  query-rest-count: Count child resources
  query-rest-paged-results: Paged results
  query-rest-sort: Server-side sort
---

# Query

|   |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| - | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|   | Examples in this documentation depend on features activated in [the `ds-evaluation` setup profile](../install-guide/setup-ds.html#about-ds-evaluation).The code samples demonstrate how to contact the server over HTTPS using the deployment CA certificate. Before trying the samples, generate the CA certificate in PEM format from the server deployment ID and password:```console
$ dskeymgr \
 export-ca-cert \
 --deploymentId $DEPLOYMENT_ID \
 --deploymentIdPassword password \
 --outputFile ca-cert.pem
``` |

To search, use HTTP GET with at least a `_queryFilter=<filter-expression>` parameter and other applicable parameters as necessary, such as `scope`. For reference details, refer to:

* [Query](rest-operations.html#query)

* [Query parameters](rest-operations.html#query-parameters)

* [Filter expressions](rest-operations.html#filter-expressions)

## Example query filters

The following table shows LDAP search filters and corresponding `_queryFilter` expressions:

| LDAP search filter(1)         | HDAP `_queryFilter`(1)              |
| ----------------------------- | ----------------------------------- |
| `(&)`                         | `true`                              |
| `(uid=*)`                     | `uid pr`                            |
| `(uid=bjensen)`               | `uid eq 'bjensen'`                  |
| `(uid=*jensen*)`              | `uid co 'jensen'`                   |
| `(uid=jensen*)`               | `uid sw 'jensen'`                   |
| `(&(uid=*jensen*)(cn=babs*))` | `uid co 'jensen' and cn sw 'babs')` |
| `(\|(uid=*jensen*)(cn=sam*))` | `(uid co 'jensen' or cn sw 'sam')`  |
| `(!(uid=*jensen*))`           | `!(uid co 'jensen')`                |
| `(uid<=jensen)`               | `uid le 'jensen'`                   |
| `(uid>=jensen)`               | `uid ge 'jensen'`                   |

(1) Quote LDAP search filters and encode HDAP `_queryFilter` parameters as necessary in your applications.

For details on which index to configure for a specific filter, refer to [Necessary indexes](../config-guide/idx-what.html#necessary-indexes).

## Build query filters

For query operations, the \<filter-expression> has the following building blocks. You must URL-encode the filter expressions. This page shows them without URL-encoding to make them easier to read.

In filter expressions, the simplest \<json-pointer> is a JSON field name. A \<json-pointer> can also reference nested elements. For details, read RFC 6901, [JavaScript Object Notation (JSON) Pointer](https://www.rfc-editor.org/rfc/rfc6901.html).

|   |                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| - | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|   | The `co` (contains) and `sw` (starts with) query filter expressions match part of a value.HDAP does not support `co` and `sw` to match values for:- Binary fields, such as photos or digital certificates (binary attributes in LDAP)

- `_id` and JSON fields whose values are the `_id`s of other resources, such as `manager` (DN attributes in LDAP)

- Time fields, such as a last login time (generalized time attributes in LDAP) |

* Comparison expressions

  Build filters using the following comparison expressions:

  * `<json-pointer> eq <json-value>`

    Matches when the pointer equals the value.

    > **Collapse: Show example**
    >
    > * Curl
    >
    > * JavaScript
    >
    > * Python
    >
    > * Ruby
    >
    > ```console
    > $ curl \
    >  --get \
    >  --cacert ca-cert.pem \
    >  --user dc=com/dc=example/ou=People/uid=kvaughan:bribery \
    >  --data "_queryFilter=mail+eq+'bjensen@example.com'" \
    >  --data '_fields=cn' \
    >  --data '_prettyPrint=true' \
    >  --data 'scope=sub' \
    >  'https://localhost:8443/hdap/dc=com/dc=example/ou=People'
    > ```
    >
    > Output
    >
    > ```
    > {
    >   "result" : [ {
    >     "_id" : "dc=com/dc=example/ou=People/uid=bjensen",
    >     "_rev" : "<revision>",
    >     "cn" : [ "Barbara Jensen", "Babs Jensen" ]
    >   } ],
    >   "resultCount" : 1,
    >   "pagedResultsCookie" : null,
    >   "totalPagedResultsPolicy" : "NONE",
    >   "totalPagedResults" : -1,
    >   "remainingPagedResults" : -1
    > }
    > ```
    >
    > ```javascript
    > (async () => {
    >     const { authenticate, doRequest, getOptions } = require('./utils')
    >     const options = getOptions({
    >         path: "/hdap/dc=com/dc=example/ou=People?_queryFilter=mail+eq+'bjensen@example.com'&_fields=cn&scope=sub"
    >     })
    >     const jwt = await authenticate(options)
    >     options.headers['Authorization'] = 'Bearer ' + jwt
    >     const response = await doRequest('HDAP: query eq', options)
    >     console.log(response)
    > })().catch(error => { console.error(error) })
    > ```
    >
    > Source files for this sample: [query-eq.js](../_attachments/hdap/js/query-eq.js), [utils.js](../_attachments/hdap/js/utils.js)
    >
    > ```python
    > #!/usr/bin/env python3
    >
    > import requests
    > import utils
    >
    > params = {
    >     '_fields': 'cn',
    >     '_queryFilter': 'mail eq "bjensen@example.com"',
    >     'scope': 'sub'
    > }
    > jwt = utils.authenticate('dc=com/dc=example/ou=People/uid=kvaughan', 'bribery')
    > headers = { 'Content-Type': 'application/json', 'Authorization': f'Bearer {jwt}' }
    > response = requests.get(
    >     f'https://{utils.host}:{utils.port}/hdap/dc=com/dc=example/ou=People',
    >     headers=headers,
    >     params=params,
    >     verify=utils.ca_pem)
    > print('Status code: %d\nJSON: %s' % (response.status_code, response.json()))
    > ```
    >
    > Source files for this sample: [utils.py](../_attachments/hdap/py/utils.py), [query-eq.py](../_attachments/hdap/py/query-eq.py)
    >
    > ```ruby
    > require_relative 'utils.rb'
    > require 'faraday'
    >
    > utils = Utils.new('dc=com/dc=example/ou=People/uid=kvaughan', 'bribery')
    > options = { ca_file: utils.ca_pem }
    > jwt = utils.authenticate
    > query = {
    >     "_fields": "cn",
    >     "_queryFilter": "mail eq 'bjensen@example.com'",
    >     "scope": "sub"
    > }
    > hdap = Faraday.new(url: "https://#{utils.host}:#{utils.port}/hdap/", params: query, ssl: options) do |f|
    >     f.headers['Content-Type'] = 'application/json'
    >     f.request :authorization, 'Bearer', jwt
    > end
    > response = hdap.get('dc=com/dc=example/ou=People')
    >
    > puts "Status code: #{response.status}\nJSON: #{response.body}"
    > ```
    >
    > Source files for this sample: [utils.rb](../_attachments/hdap/rb/utils.rb), [query-eq.rb](../_attachments/hdap/rb/query-eq.rb)
    >
    > HDAP Ruby examples require Ruby 3.2 and the `faraday` and `json` gems.

  * `<json-pointer> co <json-value>`

    Matches when the pointer contains the value.

    > **Collapse: Show example**
    >
    > * Curl
    >
    > * JavaScript
    >
    > * Python
    >
    > * Ruby
    >
    > ```console
    > $ curl \
    >  --get \
    >  --cacert ca-cert.pem \
    >  --user dc=com/dc=example/ou=People/uid=kvaughan:bribery \
    >  --data "_queryFilter=mail+co+'jensen'" \
    >  --data '_fields=cn' \
    >  --data '_prettyPrint=true' \
    >  --data 'scope=sub' \
    >  'https://localhost:8443/hdap/dc=com/dc=example/ou=People'
    > ```
    >
    > Output
    >
    > ```
    > {
    >   "result" : [ {
    >     "_id" : "dc=com/dc=example/ou=People/uid=ajensen",
    >     "_rev" : "<revision>",
    >     "cn" : [ "Allison Jensen" ]
    >   }, {
    >     "_id" : "dc=com/dc=example/ou=People/uid=bjensen",
    >     "_rev" : "<revision>",
    >     "cn" : [ "Barbara Jensen", "Babs Jensen" ]
    >   }, {
    >     "_id" : "dc=com/dc=example/ou=People/uid=gjensen",
    >     "_rev" : "<revision>",
    >     "cn" : [ "Gern Jensen" ]
    >   }, {
    >     "_id" : "dc=com/dc=example/ou=People/uid=jjensen",
    >     "_rev" : "<revision>",
    >     "cn" : [ "Jody Jensen" ]
    >   }, {
    >     "_id" : "dc=com/dc=example/ou=People/uid=kjensen",
    >     "_rev" : "<revision>",
    >     "cn" : [ "Kurt Jensen" ]
    >   }, {
    >     "_id" : "dc=com/dc=example/ou=People/uid=rjensen",
    >     "_rev" : "<revision>",
    >     "cn" : [ "Richard Jensen" ]
    >   }, {
    >     "_id" : "dc=com/dc=example/ou=People/uid=tjensen",
    >     "_rev" : "<revision>",
    >     "cn" : [ "Ted Jensen" ]
    >   } ],
    >   "resultCount" : 7,
    >   "pagedResultsCookie" : null,
    >   "totalPagedResultsPolicy" : "NONE",
    >   "totalPagedResults" : -1,
    >   "remainingPagedResults" : -1
    > }
    > ```
    >
    > ```javascript
    > (async () => {
    >     const { authenticate, doRequest, getOptions } = require('./utils')
    >     const options = getOptions({
    >         path: "/hdap/dc=com/dc=example/ou=People?_queryFilter=mail+co+'jensen'&_fields=cn&scope=sub"
    >     })
    >     const jwt = await authenticate(options)
    >     options.headers['Authorization'] = 'Bearer ' + jwt
    >     const response = await doRequest('HDAP: query co', options)
    >     console.log(response)
    > })().catch(error => { console.error(error) })
    > ```
    >
    > Source files for this sample: [query-co.js](../_attachments/hdap/js/query-co.js), [utils.js](../_attachments/hdap/js/utils.js)
    >
    > ```python
    > #!/usr/bin/env python3
    >
    > import requests
    > import utils
    >
    > params = {
    >     '_fields': 'cn',
    >     '_queryFilter': 'mail co "jensen"',
    >     'scope': 'sub'
    > }
    > jwt = utils.authenticate('dc=com/dc=example/ou=People/uid=kvaughan', 'bribery')
    > headers = { 'Content-Type': 'application/json', 'Authorization': f'Bearer {jwt}' }
    > response = requests.get(
    >     f'https://{utils.host}:{utils.port}/hdap/dc=com/dc=example/ou=People',
    >     headers=headers,
    >     params=params,
    >     verify=utils.ca_pem)
    > print('Status code: %d\nJSON: %s' % (response.status_code, response.json()))
    > ```
    >
    > Source files for this sample: [utils.py](../_attachments/hdap/py/utils.py), [query-co.py](../_attachments/hdap/py/query-co.py)
    >
    > ```ruby
    > require_relative 'utils.rb'
    > require 'faraday'
    >
    > utils = Utils.new('dc=com/dc=example/ou=People/uid=kvaughan', 'bribery')
    > options = { ca_file: utils.ca_pem }
    > jwt = utils.authenticate
    > query = {
    >     "_fields": "cn",
    >     "_queryFilter": "mail co 'jensen'",
    >     "scope": "sub"
    > }
    > hdap = Faraday.new(url: "https://#{utils.host}:#{utils.port}/hdap/", params: query, ssl: options) do |f|
    >     f.headers['Content-Type'] = 'application/json'
    >     f.request :authorization, 'Bearer', jwt
    > end
    > response = hdap.get('dc=com/dc=example/ou=People')
    >
    > puts "Status code: #{response.status}\nJSON: #{response.body}"
    > ```
    >
    > Source files for this sample: [utils.rb](../_attachments/hdap/rb/utils.rb), [query-co.rb](../_attachments/hdap/rb/query-co.rb)
    >
    > HDAP Ruby examples require Ruby 3.2 and the `faraday` and `json` gems.

  * `<json-pointer> sw <json-value>`

    Matches when the pointer starts with the value.

    > **Collapse: Show example**
    >
    > * Curl
    >
    > * JavaScript
    >
    > * Python
    >
    > * Ruby
    >
    > ```console
    > $ curl \
    >  --get \
    >  --cacert ca-cert.pem \
    >  --user dc=com/dc=example/ou=People/uid=kvaughan:bribery \
    >  --data "_queryFilter=mail+sw+'ab'" \
    >  --data '_fields=cn' \
    >  --data '_prettyPrint=true' \
    >  --data 'scope=sub' \
    >  'https://localhost:8443/hdap/dc=com/dc=example/ou=People'
    > ```
    >
    > Output
    >
    > ```
    > {
    >   "result" : [ {
    >     "_id" : "dc=com/dc=example/ou=People/uid=abarnes",
    >      "_rev" : "<revision>",
    >     "cn" : [ "Anne-Louise Barnes" ]
    >   }, {
    >     "_id" : "dc=com/dc=example/ou=People/uid=abergin",
    >     "_rev" : "<revision>",
    >     "cn" : [ "Andy Bergin" ]
    >   } ],
    >   "resultCount" : 2,
    >   "pagedResultsCookie" : null,
    >   "totalPagedResultsPolicy" : "NONE",
    >   "totalPagedResults" : -1,
    >   "remainingPagedResults" : -1
    > }
    > ```
    >
    > ```javascript
    > (async () => {
    >     const { authenticate, doRequest, getOptions } = require('./utils')
    >     const options = getOptions({
    >         path: "/hdap/dc=com/dc=example/ou=People?_queryFilter=mail+sw+'ab'&_fields=cn&scope=sub"
    >     })
    >     const jwt = await authenticate(options)
    >     options.headers['Authorization'] = 'Bearer ' + jwt
    >     const response = await doRequest('HDAP: query sw', options)
    >     console.log(response)
    > })().catch(error => { console.error(error) })
    > ```
    >
    > Source files for this sample: [query-sw.js](../_attachments/hdap/js/query-sw.js), [utils.js](../_attachments/hdap/js/utils.js)
    >
    > ```python
    > #!/usr/bin/env python3
    >
    > import requests
    > import utils
    >
    > params = {
    >     '_fields': 'cn',
    >     '_queryFilter': 'mail sw "ab"',
    >     'scope': 'sub'
    > }
    > jwt = utils.authenticate('dc=com/dc=example/ou=People/uid=kvaughan', 'bribery')
    > headers = { 'Content-Type': 'application/json', 'Authorization': f'Bearer {jwt}' }
    > response = requests.get(
    >     f'https://{utils.host}:{utils.port}/hdap/dc=com/dc=example/ou=People',
    >     headers=headers,
    >     params=params,
    >     verify=utils.ca_pem)
    > print('Status code: %d\nJSON: %s' % (response.status_code, response.json()))
    > ```
    >
    > Source files for this sample: [utils.py](../_attachments/hdap/py/utils.py), [query-sw.py](../_attachments/hdap/py/query-sw.py)
    >
    > ```ruby
    > require_relative 'utils.rb'
    > require 'faraday'
    >
    > utils = Utils.new('dc=com/dc=example/ou=People/uid=kvaughan', 'bribery')
    > options = { ca_file: utils.ca_pem }
    > jwt = utils.authenticate
    > query = {
    >     "_fields": "cn",
    >     "_queryFilter": "mail sw 'ab'",
    >     "scope": "sub"
    > }
    > hdap = Faraday.new(url: "https://#{utils.host}:#{utils.port}/hdap/", params: query, ssl: options) do |f|
    >     f.headers['Content-Type'] = 'application/json'
    >     f.request :authorization, 'Bearer', jwt
    > end
    > response = hdap.get('dc=com/dc=example/ou=People')
    >
    > puts "Status code: #{response.status}\nJSON: #{response.body}"
    > ```
    >
    > Source files for this sample: [utils.rb](../_attachments/hdap/rb/utils.rb), [query-eq.rb](../_attachments/hdap/rb/query-sw.rb)
    >
    > HDAP Ruby examples require Ruby 3.2 and the `faraday` and `json` gems.

  * `<json-pointer> lt <json-value>`

    Matches when the pointer is less than the value.

    > **Collapse: Show example**
    >
    > * Curl
    >
    > * JavaScript
    >
    > * Python
    >
    > * Ruby
    >
    > ```console
    > $ curl \
    >  --get \
    >  --cacert ca-cert.pem \
    >  --user dc=com/dc=example/ou=People/uid=kvaughan:bribery \
    >  --data "_queryFilter=mail+lt+'ac'" \
    >  --data '_fields=cn' \
    >  --data '_prettyPrint=true' \
    >  --data 'scope=sub' \
    >  'https://localhost:8443/hdap/dc=com/dc=example/ou=People'
    > ```
    >
    > Output
    >
    > ```
    > {
    >   "result" : [ {
    >     "_id" : "dc=com/dc=example/ou=People/uid=abarnes",
    >     "_rev" : "<revision>",
    >     "cn" : [ "Anne-Louise Barnes" ]
    >   }, {
    >     "_id" : "dc=com/dc=example/ou=People/uid=abergin",
    >     "_rev" : "<revision>",
    >     "cn" : [ "Andy Bergin" ]
    >   } ],
    >   "resultCount" : 2,
    >   "pagedResultsCookie" : null,
    >   "totalPagedResultsPolicy" : "NONE",
    >   "totalPagedResults" : -1,
    >   "remainingPagedResults" : -1
    > }
    > ```
    >
    > ```javascript
    > (async () => {
    >     const { authenticate, doRequest, getOptions } = require('./utils')
    >     const options = getOptions({
    >         path: "/hdap/dc=com/dc=example/ou=People?_queryFilter=mail+lt+'ac'&_fields=cn&scope=sub"
    >     })
    >     const jwt = await authenticate(options)
    >     options.headers['Authorization'] = 'Bearer ' + jwt
    >     const response = await doRequest('HDAP: query lt', options)
    >     console.log(response)
    > })().catch(error => { console.error(error) })
    > ```
    >
    > Source files for this sample: [query-lt.js](../_attachments/hdap/js/query-lt.js), [utils.js](../_attachments/hdap/js/utils.js)
    >
    > ```python
    > #!/usr/bin/env python3
    >
    > import requests
    > import utils
    >
    > params = {
    >     '_fields': 'cn',
    >     '_queryFilter': 'mail lt "ac"',
    >     'scope': 'sub'
    > }
    > jwt = utils.authenticate('dc=com/dc=example/ou=People/uid=kvaughan', 'bribery')
    > headers = { 'Content-Type': 'application/json', 'Authorization': f'Bearer {jwt}' }
    > response = requests.get(
    >     f'https://{utils.host}:{utils.port}/hdap/dc=com/dc=example/ou=People',
    >     headers=headers,
    >     params=params,
    >     verify=utils.ca_pem)
    > print('Status code: %d\nJSON: %s' % (response.status_code, response.json()))
    > ```
    >
    > Source files for this sample: [utils.py](../_attachments/hdap/py/utils.py), [query-lt.py](../_attachments/hdap/py/query-lt.py)
    >
    > ```ruby
    > require_relative 'utils.rb'
    > require 'faraday'
    >
    > utils = Utils.new('dc=com/dc=example/ou=People/uid=kvaughan', 'bribery')
    > options = { ca_file: utils.ca_pem }
    > jwt = utils.authenticate
    > query = {
    >     "_fields": "cn",
    >     "_queryFilter": "mail lt 'ac'",
    >     "scope": "sub"
    > }
    > hdap = Faraday.new(url: "https://#{utils.host}:#{utils.port}/hdap/", params: query, ssl: options) do |f|
    >     f.headers['Content-Type'] = 'application/json'
    >     f.request :authorization, 'Bearer', jwt
    > end
    > response = hdap.get('dc=com/dc=example/ou=People')
    >
    > puts "Status code: #{response.status}\nJSON: #{response.body}"
    > ```
    >
    > Source files for this sample: [utils.rb](../_attachments/hdap/rb/utils.rb), [query-lt.rb](../_attachments/hdap/rb/query-lt.rb)
    >
    > HDAP Ruby examples require Ruby 3.2 and the `faraday` and `json` gems.

  * `<json-pointer> le <json-value>`

    Matches when the pointer is less than or equal to the value.

    > **Collapse: Show example**
    >
    > * Curl
    >
    > * JavaScript
    >
    > * Python
    >
    > * Ruby
    >
    > ```console
    > $ curl \
    >  --get \
    >  --cacert ca-cert.pem \
    >  --user dc=com/dc=example/ou=People/uid=kvaughan:bribery \
    >  --data "_queryFilter=mail+le+'ad'" \
    >  --data '_fields=cn' \
    >  --data '_prettyPrint=true' \
    >  --data 'scope=sub' \
    >  'https://localhost:8443/hdap/dc=com/dc=example/ou=People'
    > ```
    >
    > Output
    >
    > ```
    > {
    >   "result" : [ {
    >     "_id" : "dc=com/dc=example/ou=People/uid=abarnes",
    >     "_rev" : "<revision>",
    >     "cn" : [ "Anne-Louise Barnes" ]
    >   }, {
    >     "_id" : "dc=com/dc=example/ou=People/uid=abergin",
    >     "_rev" : "<revision>",
    >     "cn" : [ "Andy Bergin" ]
    >   }, {
    >     "_id" : "dc=com/dc=example/ou=People/uid=achassin",
    >     "_rev" : "<revision>",
    >     "cn" : [ "Ashley Chassin" ]
    >   } ],
    >   "resultCount" : 3,
    >   "pagedResultsCookie" : null,
    >   "totalPagedResultsPolicy" : "NONE",
    >   "totalPagedResults" : -1,
    >   "remainingPagedResults" : -1
    > }
    > ```
    >
    > ```javascript
    > (async () => {
    >     const { authenticate, doRequest, getOptions } = require('./utils')
    >     const options = getOptions({
    >         path: "/hdap/dc=com/dc=example/ou=People?_queryFilter=mail+le+'ad'&_fields=cn&scope=sub"
    >     })
    >     const jwt = await authenticate(options)
    >     options.headers['Authorization'] = 'Bearer ' + jwt
    >     const response = await doRequest('HDAP: query le', options)
    >     console.log(response)
    > })().catch(error => { console.error(error) })
    > ```
    >
    > Source files for this sample: [query-le.js](../_attachments/hdap/js/query-le.js), [utils.js](../_attachments/hdap/js/utils.js)
    >
    > ```python
    > #!/usr/bin/env python3
    >
    > import requests
    > import utils
    >
    > params = {
    >     '_fields': 'cn',
    >     '_queryFilter': 'mail le "ad"',
    >     'scope': 'sub'
    > }
    > jwt = utils.authenticate('dc=com/dc=example/ou=People/uid=kvaughan', 'bribery')
    > headers = { 'Content-Type': 'application/json', 'Authorization': f'Bearer {jwt}' }
    > response = requests.get(
    >     f'https://{utils.host}:{utils.port}/hdap/dc=com/dc=example/ou=People',
    >     headers=headers,
    >     params=params,
    >     verify=utils.ca_pem)
    > print('Status code: %d\nJSON: %s' % (response.status_code, response.json()))
    > ```
    >
    > Source files for this sample: [utils.py](../_attachments/hdap/py/utils.py), [query-le.py](../_attachments/hdap/py/query-le.py)
    >
    > ```ruby
    > require_relative 'utils.rb'
    > require 'faraday'
    >
    > utils = Utils.new('dc=com/dc=example/ou=People/uid=kvaughan', 'bribery')
    > options = { ca_file: utils.ca_pem }
    > jwt = utils.authenticate
    > query = {
    >     "_fields": "cn",
    >     "_queryFilter": "mail le 'ad'",
    >     "scope": "sub"
    > }
    > hdap = Faraday.new(url: "https://#{utils.host}:#{utils.port}/hdap/", params: query, ssl: options) do |f|
    >     f.headers['Content-Type'] = 'application/json'
    >     f.request :authorization, 'Bearer', jwt
    > end
    > response = hdap.get('dc=com/dc=example/ou=People')
    >
    > puts "Status code: #{response.status}\nJSON: #{response.body}"
    > ```
    >
    > Source files for this sample: [utils.rb](../_attachments/hdap/rb/utils.rb), [query-le.rb](../_attachments/hdap/rb/query-le.rb)
    >
    > HDAP Ruby examples require Ruby 3.2 and the `faraday` and `json` gems.

  * `<json-pointer> gt <json-value>`

    Matches when the pointer is greater than the value.

    > **Collapse: Show example**
    >
    > * Curl
    >
    > * JavaScript
    >
    > * Python
    >
    > * Ruby
    >
    > ```console
    > $ curl \
    >  --get \
    >  --cacert ca-cert.pem \
    >  --user dc=com/dc=example/ou=People/uid=kvaughan:bribery \
    >  --data "_queryFilter=mail+gt+'wa'" \
    >  --data '_fields=cn' \
    >  --data '_prettyPrint=true' \
    >  --data 'scope=sub' \
    >  'https://localhost:8443/hdap/dc=com/dc=example/ou=People'
    > ```
    >
    > Output
    >
    > ```
    > {
    >   "result" : [ {
    >     "_id" : "dc=com/dc=example/ou=People/uid=wlutz",
    >     "_rev" : "<revision>",
    >     "cn" : [ "Wendy Lutz" ]
    >   } ],
    >   "resultCount" : 1,
    >   "pagedResultsCookie" : null,
    >   "totalPagedResultsPolicy" : "NONE",
    >   "totalPagedResults" : -1,
    >   "remainingPagedResults" : -1
    > }
    > ```
    >
    > ```javascript
    > (async () => {
    >     const { authenticate, doRequest, getOptions } = require('./utils')
    >     const options = getOptions({
    >         path: "/hdap/dc=com/dc=example/ou=People?_queryFilter=mail+gt+'wa'&_fields=cn&scope=sub"
    >     })
    >     const jwt = await authenticate(options)
    >     options.headers['Authorization'] = 'Bearer ' + jwt
    >     const response = await doRequest('HDAP: query gt', options)
    >     console.log(response)
    > })().catch(error => { console.error(error) })
    > ```
    >
    > Source files for this sample: [query-gt.js](../_attachments/hdap/js/query-gt.js), [utils.js](../_attachments/hdap/js/utils.js)
    >
    > ```python
    > #!/usr/bin/env python3
    >
    > import requests
    > import utils
    >
    > params = {
    >     '_fields': 'cn',
    >     '_queryFilter': 'mail gt "wa"',
    >     'scope': 'sub'
    > }
    > jwt = utils.authenticate('dc=com/dc=example/ou=People/uid=kvaughan', 'bribery')
    > headers = { 'Content-Type': 'application/json', 'Authorization': f'Bearer {jwt}' }
    > response = requests.get(
    >     f'https://{utils.host}:{utils.port}/hdap/dc=com/dc=example/ou=People',
    >     headers=headers,
    >     params=params,
    >     verify=utils.ca_pem)
    > print('Status code: %d\nJSON: %s' % (response.status_code, response.json()))
    > ```
    >
    > Source files for this sample: [utils.py](../_attachments/hdap/py/utils.py), [query-gt.py](../_attachments/hdap/py/query-gt.py)
    >
    > ```ruby
    > require_relative 'utils.rb'
    > require 'faraday'
    >
    > utils = Utils.new('dc=com/dc=example/ou=People/uid=kvaughan', 'bribery')
    > options = { ca_file: utils.ca_pem }
    > jwt = utils.authenticate
    > query = {
    >     "_fields": "cn",
    >     "_queryFilter": "mail gt 'wa'",
    >     "scope": "sub"
    > }
    > hdap = Faraday.new(url: "https://#{utils.host}:#{utils.port}/hdap/", params: query, ssl: options) do |f|
    >     f.headers['Content-Type'] = 'application/json'
    >     f.request :authorization, 'Bearer', jwt
    > end
    > response = hdap.get('dc=com/dc=example/ou=People')
    >
    > puts "Status code: #{response.status}\nJSON: #{response.body}"
    > ```
    >
    > Source files for this sample: [utils.rb](../_attachments/hdap/rb/utils.rb), [query-gt.rb](../_attachments/hdap/rb/query-gt.rb)
    >
    > HDAP Ruby examples require Ruby 3.2 and the `faraday` and `json` gems.

  * `<json-pointer> ge <json-value>`

    Matches when the pointer is greater than or equal to the value.

    > **Collapse: Show example**
    >
    > * Curl
    >
    > * JavaScript
    >
    > * Python
    >
    > * Ruby
    >
    > ```console
    > $ curl \
    >  --get \
    >  --cacert ca-cert.pem \
    >  --user dc=com/dc=example/ou=People/uid=kvaughan:bribery \
    >  --data "_queryFilter=mail+ge+'va'" \
    >  --data '_fields=cn' \
    >  --data '_prettyPrint=true' \
    >  --data 'scope=sub' \
    >  'https://localhost:8443/hdap/dc=com/dc=example/ou=People'
    > ```
    >
    > Output
    >
    > ```
    > {
    >   "result" : [ {
    >     "_id" : "dc=com/dc=example/ou=People/uid=wlutz",
    >     "_rev" : "<revision>",
    >     "cn" : [ "Wendy Lutz" ]
    >   } ],
    >   "resultCount" : 1,
    >   "pagedResultsCookie" : null,
    >   "totalPagedResultsPolicy" : "NONE",
    >   "totalPagedResults" : -1,
    >   "remainingPagedResults" : -1
    > }
    > ```
    >
    > ```javascript
    > (async () => {
    >     const { authenticate, doRequest, getOptions } = require('./utils')
    >     const options = getOptions({
    >         path: "/hdap/dc=com/dc=example/ou=People?_queryFilter=mail+ge+'va'&_fields=cn&scope=sub"
    >     })
    >     const jwt = await authenticate(options)
    >     options.headers['Authorization'] = 'Bearer ' + jwt
    >     const response = await doRequest('HDAP: query ge', options)
    >     console.log(response)
    > })().catch(error => { console.error(error) })
    > ```
    >
    > Source files for this sample: [query-ge.js](../_attachments/hdap/js/query-ge.js), [utils.js](../_attachments/hdap/js/utils.js)
    >
    > ```python
    > #!/usr/bin/env python3
    >
    > import requests
    > import utils
    >
    > params = {
    >     '_fields': 'cn',
    >     '_queryFilter': 'mail ge "va"',
    >     'scope': 'sub'
    > }
    > jwt = utils.authenticate('dc=com/dc=example/ou=People/uid=kvaughan', 'bribery')
    > headers = { 'Content-Type': 'application/json', 'Authorization': f'Bearer {jwt}' }
    > response = requests.get(
    >     f'https://{utils.host}:{utils.port}/hdap/dc=com/dc=example/ou=People',
    >     headers=headers,
    >     params=params,
    >     verify=utils.ca_pem)
    > print('Status code: %d\nJSON: %s' % (response.status_code, response.json()))
    > ```
    >
    > Source files for this sample: [utils.py](../_attachments/hdap/py/utils.py), [query-ge.py](../_attachments/hdap/py/query-ge.py)
    >
    > ```ruby
    > require_relative 'utils.rb'
    > require 'faraday'
    >
    > utils = Utils.new('dc=com/dc=example/ou=People/uid=kvaughan', 'bribery')
    > options = { ca_file: utils.ca_pem }
    > jwt = utils.authenticate
    > query = {
    >     "_fields": "cn",
    >     "_queryFilter": "mail ge 'va'",
    >     "scope": "sub"
    > }
    > hdap = Faraday.new(url: "https://#{utils.host}:#{utils.port}/hdap/", params: query, ssl: options) do |f|
    >     f.headers['Content-Type'] = 'application/json'
    >     f.request :authorization, 'Bearer', jwt
    > end
    > response = hdap.get('dc=com/dc=example/ou=People')
    >
    > puts "Status code: #{response.status}\nJSON: #{response.body}"
    > ```
    >
    > Source files for this sample: [utils.rb](../_attachments/hdap/rb/utils.rb), [query-ge.rb](../_attachments/hdap/rb/query-ge.rb)
    >
    > HDAP Ruby examples require Ruby 3.2 and the `faraday` and `json` gems.

* Presence expression

  `<json-pointer> pr` matches a resource where the pointer is present.

  > **Collapse: Show example**
  >
  > * Curl
  >
  > * JavaScript
  >
  > * Python
  >
  > * Ruby
  >
  > ```console
  > $ curl \
  >  --get \
  >  --cacert ca-cert.pem \
  >  --user dc=com/dc=example/ou=People/uid=kvaughan:bribery \
  >  --data "_queryFilter=cn+pr" \
  >  --data '_fields=cn' \
  >  --data '_prettyPrint=true' \
  >  --data 'scope=sub' \
  >  'https://localhost:8443/hdap/dc=com/dc=example/ou=Groups'
  > ```
  >
  > Output
  >
  > ```
  > {
  >   "result" : [ {
  >     "_id" : "dc=com/dc=example/ou=groups/cn=Accounting%20Managers",
  >     "_rev" : "<revision>",
  >     "cn" : [ "Accounting Managers" ]
  >   }, {
  >     "_id" : "dc=com/dc=example/ou=Groups/cn=Directory%20Administrators",
  >     "_rev" : "<revision>",
  >     "cn" : [ "Directory Administrators" ]
  >   }, {
  >     "_id" : "dc=com/dc=example/ou=groups/cn=HR%20Managers",
  >     "_rev" : "<revision>",
  >     "cn" : [ "HR Managers" ]
  >   }, {
  >     "_id" : "dc=com/dc=example/ou=groups/cn=PD%20Managers",
  >     "_rev" : "<revision>",
  >     "cn" : [ "PD Managers" ]
  >   }, {
  >     "_id" : "dc=com/dc=example/ou=groups/cn=QA%20Managers",
  >     "_rev" : "<revision>",
  >     "cn" : [ "QA Managers" ]
  >   }, {
  >     "_id" : "dc=com/dc=example/ou=Groups/ou=Self%20Service/cn=Carpoolers",
  >     "_rev" : "<revision>",
  >     "cn" : [ "Carpoolers" ]
  >   } ],
  >   "resultCount" : 6,
  >   "pagedResultsCookie" : null,
  >   "totalPagedResultsPolicy" : "NONE",
  >   "totalPagedResults" : -1,
  >   "remainingPagedResults" : -1
  > }
  > ```
  >
  > ```javascript
  > (async () => {
  >     const { authenticate, doRequest, getOptions } = require('./utils')
  >     const options = getOptions({
  >         path: '/hdap/dc=com/dc=example/ou=Groups?_queryFilter=cn+pr&_fields=cn&scope=sub'
  >     })
  >     const jwt = await authenticate(options)
  >     options.headers['Authorization'] = 'Bearer ' + jwt
  >     const response = await doRequest('HDAP: query pr', options)
  >     console.log(response)
  > })().catch(error => { console.error(error) })
  > ```
  >
  > Source files for this sample: [query-pr.js](../_attachments/hdap/js/query-pr.js), [utils.js](../_attachments/hdap/js/utils.js)
  >
  > ```python
  > #!/usr/bin/env python3
  >
  > import requests
  > import utils
  >
  > params = {
  >     '_fields': 'cn',
  >     '_queryFilter': 'cn pr',
  >     'scope': 'sub'
  > }
  > jwt = utils.authenticate('dc=com/dc=example/ou=People/uid=kvaughan', 'bribery')
  > headers = { 'Content-Type': 'application/json', 'Authorization': f'Bearer {jwt}' }
  > response = requests.get(
  >     f'https://{utils.host}:{utils.port}/hdap/dc=com/dc=example/ou=Groups',
  >     headers=headers,
  >     params=params,
  >     verify=utils.ca_pem)
  > print('Status code: %d\nJSON: %s' % (response.status_code, response.json()))
  > ```
  >
  > Source files for this sample: [utils.py](../_attachments/hdap/py/utils.py), [query-pr.py](../_attachments/hdap/py/query-pr.py)
  >
  > ```ruby
  > require_relative 'utils.rb'
  > require 'faraday'
  >
  > utils = Utils.new('dc=com/dc=example/ou=People/uid=kvaughan', 'bribery')
  > options = { ca_file: utils.ca_pem }
  > jwt = utils.authenticate
  > query = {
  >     "_fields": "cn",
  >     "_queryFilter": "cn pr",
  >     "scope": "sub"
  > }
  > hdap = Faraday.new(url: "https://#{utils.host}:#{utils.port}/hdap/", params: query, ssl: options) do |f|
  >     f.headers['Content-Type'] = 'application/json'
  >     f.request :authorization, 'Bearer', jwt
  > end
  > response = hdap.get('dc=com/dc=example/ou=Groups')
  >
  > puts "Status code: #{response.status}\nJSON: #{response.body}"
  > ```
  >
  > Source files for this sample: [utils.rb](../_attachments/hdap/rb/utils.rb), [query-pr.rb](../_attachments/hdap/rb/query-pr.rb)
  >
  > HDAP Ruby examples require Ruby 3.2 and the `faraday` and `json` gems.

* Literal expressions

  `true` matches any resource in scope.

  `false` matches no resources.

  > **Collapse: Show example**
  >
  > * Curl
  >
  > * JavaScript
  >
  > * Python
  >
  > * Ruby
  >
  > ```console
  > $ curl \
  >  --get \
  >  --cacert ca-cert.pem \
  >  --user dc=com/dc=example/ou=People/uid=kvaughan:bribery \
  >  --data "_queryFilter=true" \
  >  --data '_fields=_id' \
  >  --data '_prettyPrint=true' \
  >  'https://localhost:8443/hdap/dc=com/dc=example/ou=Groups'
  > ```
  >
  > Output
  >
  > ```
  > {
  >   "result" : [ {
  >     "_id" : "dc=com/dc=example/ou=groups/cn=Accounting%20Managers",
  >     "_rev" : "<revision>"
  >   }, {
  >     "_id" : "dc=com/dc=example/ou=Groups/cn=Directory%20Administrators",
  >     "_rev" : "<revision>"
  >   }, {
  >     "_id" : "dc=com/dc=example/ou=groups/cn=HR%20Managers",
  >     "_rev" : "<revision>"
  >   }, {
  >     "_id" : "dc=com/dc=example/ou=groups/cn=PD%20Managers",
  >     "_rev" : "<revision>"
  >   }, {
  >     "_id" : "dc=com/dc=example/ou=groups/cn=QA%20Managers",
  >     "_rev" : "<revision>"
  >   }, {
  >     "_id" : "dc=com/dc=example/ou=Groups/ou=Self%20Service",
  >     "_rev" : "<revision>"
  >   } ],
  >   "resultCount" : 6,
  >   "pagedResultsCookie" : null,
  >   "totalPagedResultsPolicy" : "NONE",
  >   "totalPagedResults" : -1,
  >   "remainingPagedResults" : -1
  > }
  > ```
  >
  > ```javascript
  > (async () => {
  >     const { authenticate, doRequest, getOptions } = require('./utils')
  >     const options = getOptions({
  >         path: '/hdap/dc=com/dc=example/ou=Groups?_queryFilter=true&_fields=cn&scope=sub'
  >     })
  >     const jwt = await authenticate(options)
  >     options.headers['Authorization'] = 'Bearer ' + jwt
  >     const response = await doRequest('HDAP: query true', options)
  >     console.log(response)
  > })().catch(error => { console.error(error) })
  > ```
  >
  > Source files for this sample: [query-true.js](../_attachments/hdap/js/query-true.js), [utils.js](../_attachments/hdap/js/utils.js)
  >
  > ```python
  > #!/usr/bin/env python3
  >
  > import requests
  > import utils
  >
  > params = {
  >     '_fields': 'cn',
  >     '_queryFilter': True,
  >     'scope': 'sub'
  > }
  > jwt = utils.authenticate('dc=com/dc=example/ou=People/uid=kvaughan', 'bribery')
  > headers = { 'Content-Type': 'application/json', 'Authorization': f'Bearer {jwt}' }
  > response = requests.get(
  >     f'https://{utils.host}:{utils.port}/hdap/dc=com/dc=example/ou=Groups',
  >     headers=headers,
  >     params=params,
  >     verify=utils.ca_pem)
  > print('Status code: %d\nJSON: %s' % (response.status_code, response.json()))
  > ```
  >
  > Source files for this sample: [utils.py](../_attachments/hdap/py/utils.py), [query-true.py](../_attachments/hdap/py/query-true.py)
  >
  > ```ruby
  > require_relative 'utils.rb'
  > require 'faraday'
  >
  > utils = Utils.new('dc=com/dc=example/ou=People/uid=kvaughan', 'bribery')
  > options = { ca_file: utils.ca_pem }
  > jwt = utils.authenticate
  > query = {
  >     "_fields": "cn",
  >     "_queryFilter": true,
  >     "scope": "sub"
  > }
  > hdap = Faraday.new(url: "https://#{utils.host}:#{utils.port}/hdap/", params: query, ssl: options) do |f|
  >     f.headers['Content-Type'] = 'application/json'
  >     f.request :authorization, 'Bearer', jwt
  > end
  > response = hdap.get('dc=com/dc=example/ou=Groups')
  >
  > puts "Status code: #{response.status}\nJSON: #{response.body}"
  > ```
  >
  > Source files for this sample: [utils.rb](../_attachments/hdap/rb/utils.rb), [query-true.rb](../_attachments/hdap/rb/query-true.rb)
  >
  > HDAP Ruby examples require Ruby 3.2 and the `faraday` and `json` gems.

* Complex expressions

  Combine expressions using boolean operators `and`, `or`, and `!` (not), and by using parentheses `(<filter-expression>)` with group expressions.

  > **Collapse: Show example**
  >
  > * Curl
  >
  > * JavaScript
  >
  > * Python
  >
  > * Ruby
  >
  > ```console
  > $ curl \
  >  --get \
  >  --cacert ca-cert.pem \
  >  --user dc=com/dc=example/ou=People/uid=kvaughan:bribery \
  >  --data "_queryFilter=mail+co+'jensen'+and+givenName+sw+'Al'" \
  >  --data '_fields=cn' \
  >  --data '_prettyPrint=true' \
  >  --data 'scope=sub' \
  >  'https://localhost:8443/hdap/dc=com/dc=example/ou=People'
  > ```
  >
  > Output
  >
  > ```
  > {
  >   "result" : [ {
  >     "_id" : "dc=com/dc=example/ou=People/uid=ajensen",
  >     "_rev" : "<revision>",
  >     "cn" : [ "Allison Jensen" ]
  >   } ],
  >   "resultCount" : 1,
  >   "pagedResultsCookie" : null,
  >   "totalPagedResultsPolicy" : "NONE",
  >   "totalPagedResults" : -1,
  >   "remainingPagedResults" : -1
  > }
  > ```
  >
  > ```javascript
  > (async () => {
  >     const { authenticate, doRequest, getOptions } = require('./utils')
  >     const filter = encodeURIComponent("mail co 'jensen' and givenName sw 'Al'")
  >     const options = getOptions({
  >         path: `/hdap/dc=com/dc=example/ou=People?_queryFilter=${filter}&_fields=cn&scope=sub`
  >     })
  >     const jwt = await authenticate(options)
  >     options.headers['Authorization'] = 'Bearer ' + jwt
  >     const response = await doRequest('HDAP: complex query', options)
  >     console.log(response)
  > })().catch(error => { console.error(error) })
  > ```
  >
  > Source files for this sample: [query-complex.js](../_attachments/hdap/js/query-complex.js), [utils.js](../_attachments/hdap/js/utils.js)
  >
  > ```python
  > #!/usr/bin/env python3
  >
  > import requests
  > import utils
  >
  > params = {
  >     '_fields': 'cn',
  >     '_queryFilter': 'mail co "jensen" and givenName sw "Al"',
  >     'scope': 'sub'
  > }
  > jwt = utils.authenticate('dc=com/dc=example/ou=People/uid=kvaughan', 'bribery')
  > headers = { 'Content-Type': 'application/json', 'Authorization': f'Bearer {jwt}' }
  > response = requests.get(
  >     f'https://{utils.host}:{utils.port}/hdap/dc=com/dc=example/ou=People',
  >     headers=headers,
  >     params=params,
  >     verify=utils.ca_pem)
  > print('Status code: %d\nJSON: %s' % (response.status_code, response.json()))
  > ```
  >
  > Source files for this sample: [utils.py](../_attachments/hdap/py/utils.py), [query-complex.py](../_attachments/hdap/py/query-complex.py)
  >
  > ```ruby
  > require_relative 'utils.rb'
  > require 'faraday'
  >
  > utils = Utils.new('dc=com/dc=example/ou=People/uid=kvaughan', 'bribery')
  > options = { ca_file: utils.ca_pem }
  > jwt = utils.authenticate
  > query = {
  >     "_fields": "cn",
  >     "_queryFilter": "mail co 'jensen' and givenName sw 'Al'",
  >     "scope": "sub"
  > }
  > hdap = Faraday.new(url: "https://#{utils.host}:#{utils.port}/hdap/", params: query, ssl: options) do |f|
  >     f.headers['Content-Type'] = 'application/json'
  >     f.request :authorization, 'Bearer', jwt
  > end
  > response = hdap.get('dc=com/dc=example/ou=People')
  >
  > puts "Status code: #{response.status}\nJSON: #{response.body}"
  > ```
  >
  > Source files for this sample: [utils.rb](../_attachments/hdap/rb/utils.rb), [query-complex.rb](../_attachments/hdap/rb/query-complex.rb)
  >
  > HDAP Ruby examples require Ruby 3.2 and the `faraday` and `json` gems.

## Graph-like queries

[Collective attributes](../config-guide/collective-attrs.html) provide a mechanism to inherit LDAP attributes from other entries. HDAP relies on this mechanism for graph-like queries.

The `ds-evaluation` setup profile uses collective attributes to inherit LDAP attribute values for street address from location and quota settings from class of service.

> **Collapse: Show example**
>
> * Curl
>
> * JavaScript
>
> * Python
>
> * Ruby
>
> ```console
> $ curl \
>  --get \
>  --cacert ca-cert.pem \
>  --user dc=com/dc=example/ou=People/uid=kvaughan:bribery \
>  --data "_queryFilter=(mail+co+'jensen'+and+l+eq+'San+Francisco'+and+classOfService+eq+'bronze')" \
>  --data '_fields=diskQuota,mailQuota,street' \
>  --data '_prettyPrint=true' \
>  --data 'scope=sub' \
>  'https://localhost:8443/hdap/dc=com/dc=example/ou=People'
> ```
>
> Output
>
> ```
> {
>   "result" : [ {
>     "_id" : "dc=com/dc=example/ou=People/uid=bjensen",
>     "_rev" : "<revision>",
>     "street" : [ "201 Mission Street Suite 2900" ],
>     "mailQuota" : [ "1 GB" ],
>     "diskQuota" : [ "10 GB" ]
>   } ],
>   "resultCount" : 1,
>   "pagedResultsCookie" : null,
>   "totalPagedResultsPolicy" : "NONE",
>   "totalPagedResults" : -1,
>   "remainingPagedResults" : -1
> }
> ```
>
> ```javascript
> (async () => {
>     const { authenticate, doRequest, getOptions } = require('./utils')
>     const filter = "mail+co+'jensen'+and+l+eq+'San+Francisco'+and+classOfService+eq+'bronze'"
>     const options = getOptions({
>         path: `/hdap/dc=com/dc=example/ou=People?_queryFilter=${filter}&_fields=diskQuota,mailQuota,street&scope=sub`
>     })
>     const jwt = await authenticate(options)
>     options.headers['Authorization'] = 'Bearer ' + jwt
>     const response = await doRequest('HDAP: graph query', options)
>     console.log(response)
> })().catch(error => { console.error(error) })
> ```
>
> Source files for this sample: [query-graph.js](../_attachments/hdap/js/query-graph.js), [utils.js](../_attachments/hdap/js/utils.js)
>
> ```python
> #!/usr/bin/env python3
>
> import requests
> import utils
>
> params = {
>     '_fields': 'diskQuota,mailQuota,street',
>     '_queryFilter': 'mail co "jensen" and l eq "San Francisco" and classOfService eq "bronze"',
>     'scope': 'sub'
> }
> jwt = utils.authenticate('dc=com/dc=example/ou=People/uid=kvaughan', 'bribery')
> headers = { 'Content-Type': 'application/json', 'Authorization': f'Bearer {jwt}' }
> response = requests.get(
>     f'https://{utils.host}:{utils.port}/hdap/dc=com/dc=example/ou=People',
>     headers=headers,
>     params=params,
>     verify=utils.ca_pem)
> print('Status code: %d\nJSON: %s' % (response.status_code, response.json()))
> ```
>
> Source files for this sample: [utils.py](../_attachments/hdap/py/utils.py), [query-graph.py](../_attachments/hdap/py/query-graph.py)
>
> ```ruby
> require_relative 'utils.rb'
> require 'faraday'
>
> utils = Utils.new('dc=com/dc=example/ou=People/uid=kvaughan', 'bribery')
> options = { ca_file: utils.ca_pem }
> jwt = utils.authenticate
> query = {
>     "_fields": "diskQuota,mailQuota,street",
>     "_queryFilter": "mail co 'jensen' and l eq 'San Francisco' and classOfService eq 'bronze'",
>     "scope": "sub"
> }
> hdap = Faraday.new(url: "https://#{utils.host}:#{utils.port}/hdap/", params: query, ssl: options) do |f|
>     f.headers['Content-Type'] = 'application/json'
>     f.request :authorization, 'Bearer', jwt
> end
> response = hdap.get('dc=com/dc=example/ou=People')
>
> puts "Status code: #{response.status}\nJSON: #{response.body}"
> ```
>
> Source files for this sample: [utils.rb](../_attachments/hdap/rb/utils.rb), [query-graph.rb](../_attachments/hdap/rb/query-graph.rb)
>
> HDAP Ruby examples require Ruby 3.2 and the `faraday` and `json` gems.

Configure collective attributes as necessary for your graph-like queries.

## Queries and JSON attributes

The default JSON query index works for JSON attributes that hold arbitrary JSON objects. This includes JSON with nested objects, such as `{"array":[{"x":1,"y":2},{"x":3,"y":4}]}`. As a result, HDAP filter expressions can target JSON fields in indexed JSON attribute objects.

HDAP query filter expressions support the [grouping operators](https://www.rfc-editor.org/rfc/rfc7644.html#section-3.4.2.2) described in RFC 7644, section *3.4.2.2. Filtering*, Table 5: *Grouping Operators*. In other words, HDAP query filter expressions can use *complex attribute filter grouping*, with brackets (`[]`) to group expressions in the filter.

Complex attribute filter grouping lets filter expressions target array objects. This search finds an entry with a `json` attribute containing an `array` of objects:

* Curl

* JavaScript

* Python

* Ruby

```console
$ curl \
 --get \
 --cacert ca-cert.pem \
 --user dc=com/dc=example/ou=People/uid=kvaughan:bribery \
 --data-urlencode "_queryFilter=(json/array[x eq 1] and json/array[y eq 4])" \
 --data '_fields=json' \
 --data '_prettyPrint=true' \
 --data 'scope=sub' \
 'https://localhost:8443/hdap/dc=com/dc=example/ou=People'
```

> **Collapse: Show output**
>
> ```
> {
>   "result" : [ {
>     "_id" : "dc=com/dc=example/ou=People/uid=abarnes",
>     "_rev" : "<revision>",
>     "json" : [ {
>       "array" : [ {
>         "x" : 1,
>         "y" : 2
>       }, {
>         "x" : 3,
>         "y" : 4
>       } ]
>     } ]
>   } ],
>   "resultCount" : 1,
>   "pagedResultsCookie" : null,
>   "totalPagedResultsPolicy" : "NONE",
>   "totalPagedResults" : -1,
>   "remainingPagedResults" : -1
> }
> ```

```javascript
(async () => {
    const { authenticate, doRequest, getOptions } = require('./utils')
    const filter = encodeURIComponent('(json/array[x eq 1] and json/array[y eq 4])')
    const options = getOptions({
        path: `/hdap/dc=com/dc=example/ou=People?_queryFilter=${filter}&_fields=json&scope=sub`
    })
    const jwt = await authenticate(options)
    options.headers['Authorization'] = 'Bearer ' + jwt
    const response = await doRequest('HDAP: JSON query', options)
    console.log(response)
})().catch(error => { console.error(error) })
```

Source files for this sample: [query-json.js](../_attachments/hdap/js/query-json.js), [utils.js](../_attachments/hdap/js/utils.js)

```python
#!/usr/bin/env python3

import requests
import utils

params = {
    '_fields': 'json',
    '_queryFilter': '(json/array[x eq 1] and json/array[y eq 4])',
    'scope': 'sub'
}
jwt = utils.authenticate('dc=com/dc=example/ou=People/uid=kvaughan', 'bribery')
headers = { 'Content-Type': 'application/json', 'Authorization': f'Bearer {jwt}' }
response = requests.get(
    f'https://{utils.host}:{utils.port}/hdap/dc=com/dc=example/ou=People',
    headers=headers,
    params=params,
    verify=utils.ca_pem)
print('Status code: %d\nJSON: %s' % (response.status_code, response.json()))
```

Source files for this sample: [utils.py](../_attachments/hdap/py/utils.py), [query-json.py](../_attachments/hdap/py/query-json.py)

```ruby
require_relative 'utils.rb'
require 'faraday'

utils = Utils.new('dc=com/dc=example/ou=People/uid=kvaughan', 'bribery')
options = { ca_file: utils.ca_pem }
jwt = utils.authenticate
query = {
    "_fields": "json",
    "_queryFilter": "(json/array[x eq 1] and json/array[y eq 4])",
    "scope": "sub"
}
hdap = Faraday.new(url: "https://#{utils.host}:#{utils.port}/hdap/", params: query, ssl: options) do |f|
    f.headers['Content-Type'] = 'application/json'
    f.request :authorization, 'Bearer', jwt
end
response = hdap.get('dc=com/dc=example/ou=People')

puts "Status code: #{response.status}\nJSON: #{response.body}"
```

Source files for this sample: [utils.rb](../_attachments/hdap/rb/utils.rb), [query-json.rb](../_attachments/hdap/rb/query-json.rb)

HDAP Ruby examples require Ruby 3.2 and the `faraday` and `json` gems.

* The filter `json/array[x eq 1] and json/array[y eq 4]` matches because it matches both objects in the array.

* The filter `json/array[x eq 1 and y eq 2]` matches because it matches the first object of the array.

* The filter `json/array[x eq 1 and y eq 4]` fails to match, because the array has no object `{"x":1,"y":4}`.

## Count child resources

Use the `_countOnly=true` query string parameter to get the number of child resources directly beneath a resource. You must also set `_queryFilter=true` and leave `scope=one` (default):

* Curl

* JavaScript

* Python

* Ruby

```console
$ curl \
 --get \
 --user dc=com/dc=example/ou=People/uid=kvaughan:bribery \
 --cacert ca-cert.pem \
 --header 'Accept-API-Version: protocol=2.2,resource=1.0' \
 --data '_countOnly=true' \
 --data '_queryFilter=true' \
 --data '_prettyPrint=true' \
 'https://localhost:8443/hdap/dc=com/dc=example/ou=People'
```

> **Collapse: Show output**
>
> ```
> {
>   "result" : [ ],
>   "resultCount" : 100153,
>   "pagedResultsCookie" : null,
>   "totalPagedResultsPolicy" : "ESTIMATE",
>   "totalPagedResults" : 100153,
>   "remainingPagedResults" : -1
> }
> ```

```javascript
(async () => {
    const { authenticate, doRequest, getOptions } = require('./utils')
    const options = getOptions({
        path: '/hdap/dc=com/dc=example/ou=People?_queryFilter=true&_countOnly=true',
    })
    const jwt = await authenticate(options)
    options.headers['Accept-API-Version'] = 'protocol=2.2,resource=1.0'
    options.headers['Authorization'] = 'Bearer ' + jwt
    const response = await doRequest('HDAP: query for count', options)
    console.log(response)
})().catch(error => { console.error(error) })
```

Source files for this sample: [query-count.js](../_attachments/hdap/js/query-count.js), [utils.js](../_attachments/hdap/js/utils.js)

```python
#!/usr/bin/env python3

import requests
import utils

params = {
    '_countOnly': True,
    '_queryFilter': True
}
jwt = utils.authenticate('dc=com/dc=example/ou=People/uid=kvaughan', 'bribery')
headers = {
    'Content-Type': 'application/json',
    'Authorization': f'Bearer {jwt}',
    'Accept-API-Version': 'protocol=2.2,resource=1.0'
}
response = requests.get(
    f'https://{utils.host}:{utils.port}/hdap/dc=com/dc=example/ou=People',
    headers=headers,
    params=params,
    verify=utils.ca_pem)
print('Status code: %d\nJSON: %s' % (response.status_code, response.json()))
```

Source files for this sample: [utils.py](../_attachments/hdap/py/utils.py), [query-count.py](../_attachments/hdap/py/query-count.py)

```ruby
require_relative 'utils.rb'
require 'faraday'

utils = Utils.new('dc=com/dc=example/ou=People/uid=kvaughan', 'bribery')
options = { ca_file: utils.ca_pem }
jwt = utils.authenticate
query = {
    "_countOnly": true,
    "_queryFilter": true
}
hdap = Faraday.new(url: "https://#{utils.host}:#{utils.port}/hdap/", params: query, ssl: options) do |f|
    f.headers['Content-Type'] = 'application/json'
    f.headers['Accept-API-Version'] = 'protocol=2.2,resource=1.0'
    f.request :authorization, 'Bearer', jwt
end
response = hdap.get('dc=com/dc=example/ou=People')

puts "Status code: #{response.status}\nJSON: #{response.body}"
```

Source files for this sample: [utils.rb](../_attachments/hdap/rb/utils.rb), [query-count.rb](../_attachments/hdap/rb/query-count.rb)

HDAP Ruby examples require Ruby 3.2 and the `faraday` and `json` gems.

Notice the search returns an empty `result` array. This feature relies on the [`numSubordinates` virtual attribute](../config-guide/virtual-attrs.html#default-virtual-attributes).

## Paged results

Get results one page at a time with these [query string parameters](rest-operations.html#query-parameters):

* `_pageSize=<number>`

* `_pagedResultsCookie=<cookie>`

> **Collapse: Show request for first page of five results**
>
> * Curl
>
> * JavaScript
>
> * Python
>
> * Ruby
>
> ```console
> $ curl \
>  --get \
>  --cacert ca-cert.pem \
>  --user dc=com/dc=example/ou=People/uid=kvaughan:bribery \
>  --data "_queryFilter=objectClass+eq+'posixAccount'" \
>  --data '_pageSize=5' \
>  --data '_fields=_id' \
>  --data '_prettyPrint=true' \
>  --data 'scope=sub' \
>  'https://localhost:8443/hdap/dc=com/dc=example/ou=People'
> ```
>
> Output
>
> ```
> {
>   "result" : [ {
>     "_id" : "dc=com/dc=example/ou=People/uid=abarnes",
>     "_rev" : "<revision>"
>   }, {
>     "_id" : "dc=com/dc=example/ou=People/uid=abergin",
>     "_rev" : "<revision>"
>   }, {
>     "_id" : "dc=com/dc=example/ou=People/uid=achassin",
>     "_rev" : "<revision>"
>   }, {
>     "_id" : "dc=com/dc=example/ou=People/uid=ahall",
>     "_rev" : "<revision>"
>   }, {
>     "_id" : "dc=com/dc=example/ou=People/uid=ahel",
>     "_rev" : "<revision>"
>   } ],
>   "resultCount" : 5,
>   "pagedResultsCookie" : "AAAAAAAAABE=",
>   "totalPagedResultsPolicy" : "NONE",
>   "totalPagedResults" : -1,
>   "remainingPagedResults" : -1
> }
> ```
>
> ```javascript
> (async () => {
>     const { authenticate, doRequest, getOptions } = require('./utils')
>     const filter = "objectClass+eq+'posixAccount'"
>     const options = getOptions({
>         path: `/hdap/dc=com/dc=example/ou=People?_queryFilter=${filter}&_pageSize=5&_fields=_id&scope=sub`
>     })
>     const jwt = await authenticate(options)
>     options.headers['Authorization'] = 'Bearer ' + jwt
>     const response = await doRequest('HDAP: query first five paged results', options)
>     console.log(response)
> })().catch(error => { console.error(error) })
> ```
>
> Source files for this sample: [query-paged-first-five.js](../_attachments/hdap/js/query-paged-first-five.js), [utils.js](../_attachments/hdap/js/utils.js)
>
> ```python
> #!/usr/bin/env python3
>
> import requests
> import utils
>
> params = {
>     '_fields': '_id',
>     '_queryFilter': 'objectClass eq "posixAccount"',
>     '_pageSize': 5,
>     'scope': 'sub'
> }
> jwt = utils.authenticate('dc=com/dc=example/ou=People/uid=kvaughan', 'bribery')
> headers = { 'Content-Type': 'application/json', 'Authorization': f'Bearer {jwt}' }
> response = requests.get(
>     f'https://{utils.host}:{utils.port}/hdap/dc=com/dc=example/ou=People',
>     headers=headers,
>     params=params,
>     verify=utils.ca_pem)
> print('Status code: %d\nJSON: %s' % (response.status_code, response.json()))
> ```
>
> Source files for this sample: [utils.py](../_attachments/hdap/py/utils.py), [query-paged-first-five.py](../_attachments/hdap/py/query-paged-first-five.py)
>
> ```ruby
> require_relative 'utils.rb'
> require 'faraday'
>
> utils = Utils.new('dc=com/dc=example/ou=People/uid=kvaughan', 'bribery')
> options = { ca_file: utils.ca_pem }
> jwt = utils.authenticate
> query = {
>     "_fields": "_id",
>     "_queryFilter": "objectClass eq 'posixAccount'",
>     "_pageSize": 5,
>     "scope": "sub"
> }
> hdap = Faraday.new(url: "https://#{utils.host}:#{utils.port}/hdap/", params: query, ssl: options) do |f|
>     f.headers['Content-Type'] = 'application/json'
>     f.request :authorization, 'Bearer', jwt
> end
> response = hdap.get('dc=com/dc=example/ou=People')
>
> puts "Status code: #{response.status}\nJSON: #{response.body}"
> ```
>
> Source files for this sample: [utils.rb](../_attachments/hdap/rb/utils.rb), [query-paged-first-five.rb](../_attachments/hdap/rb/query-paged-first-five.rb)
>
> HDAP Ruby examples require Ruby 3.2 and the `faraday` and `json` gems.

> **Collapse: Show request for next page of five results**
>
> * Curl
>
> * JavaScript
>
> * Python
>
> * Ruby
>
> ```console
> $ export COOKIE=$(cut -d \" -f 4 <(grep pagedResultsCookie \
>  <(curl \
>  --get \
>  --cacert ca-cert.pem \
>  --user dc=com/dc=example/ou=People/uid=kvaughan:bribery \
>  --data "_queryFilter=objectClass+eq+'posixAccount'" \
>  --data '_pageSize=5' \
>  --data '_fields=_id' \
>  --data '_prettyPrint=true' \
>  --data 'scope=sub' \
>  'https://localhost:8443/hdap/dc=com/dc=example/ou=People')))
> $ curl \
>  --get \
>  --cacert ca-cert.pem \
>  --user dc=com/dc=example/ou=People/uid=kvaughan:bribery \
>  --data "_queryFilter=objectClass+eq+'posixAccount'" \
>  --data '_pageSize=5' \
>  --data "_pagedResultsCookie=$COOKIE" \
>  --data '_fields=_id' \
>  --data '_prettyPrint=true' \
>  --data 'scope=sub' \
>  'https://localhost:8443/hdap/dc=com/dc=example/ou=People'
> ```
>
> Output
>
> ```
> {
>   "result" : [ {
>     "_id" : "dc=com/dc=example/ou=People/uid=ahunter",
>     "_rev" : "<revision>"
>   }, {
>     "_id" : "dc=com/dc=example/ou=People/uid=ajensen",
>     "_rev" : "<revision>"
>   }, {
>     "_id" : "dc=com/dc=example/ou=People/uid=aknutson",
>     "_rev" : "<revision>"
>   }, {
>     "_id" : "dc=com/dc=example/ou=People/uid=alangdon",
>     "_rev" : "<revision>"
>   }, {
>     "_id" : "dc=com/dc=example/ou=People/uid=alutz",
>     "_rev" : "<revision>"
>   } ],
>   "resultCount" : 5,
>   "pagedResultsCookie" : "AAAAAAAAABE=",
>   "totalPagedResultsPolicy" : "NONE",
>   "totalPagedResults" : -1,
>   "remainingPagedResults" : -1
> }
> ```
>
> ```javascript
> (async () => {
>     const { authenticate, doRequest, getOptions } = require('./utils')
>     const filter = "objectClass+eq+'posixAccount'"
>     const options = getOptions({
>         path: `/hdap/dc=com/dc=example/ou=People?_queryFilter=${filter}&_pageSize=5&_fields=_id&scope=sub`
>     })
>     const jwt = await authenticate(options)
>     options.headers['Authorization'] = 'Bearer ' + jwt
>     let response = await doRequest('HDAP: query first five paged results', options)
>     console.log(response)
>     const cookie = JSON.parse(response.data).pagedResultsCookie
>     options.path += `&_pagedResultsCookie=${cookie}`
>     response = await doRequest('HDAP: query next five paged results', options)
>     console.log(response)
> })().catch(error => { console.error(error) })
> ```
>
> Source files for this sample: [query-paged-next-five.js](../_attachments/hdap/js/query-paged-next-five.js), [utils.js](../_attachments/hdap/js/utils.js)
>
> ```python
> #!/usr/bin/env python3
>
> import requests
> import utils
>
> resource = f'https://{utils.host}:{utils.port}/hdap/dc=com/dc=example/ou=People'
> params = {
>     '_fields': '_id',
>     '_queryFilter': 'objectClass eq "posixAccount"',
>     '_pageSize': 5,
>     'scope': 'sub'
> }
> jwt = utils.authenticate('dc=com/dc=example/ou=People/uid=kvaughan', 'bribery')
> headers = { 'Content-Type': 'application/json', 'Authorization': f'Bearer {jwt}' }
> response = requests.get(
>     resource,
>     headers=headers,
>     params=params,
>     verify=utils.ca_pem)
>
> cookie = response.json()['pagedResultsCookie']
> params['_pagedResultsCookie'] = cookie
>
> response = requests.get(
>     resource,
>     headers=headers,
>     params=params,
>     verify=utils.ca_pem)
> print('Status code: %d\nJSON: %s' % (response.status_code, response.json()))
> ```
>
> Source files for this sample: [utils.py](../_attachments/hdap/py/utils.py), [query-paged-next-five.py](../_attachments/hdap/py/query-paged-next-five.py)
>
> ```ruby
> require_relative 'utils.rb'
> require 'faraday'
>
> utils = Utils.new('dc=com/dc=example/ou=People/uid=kvaughan', 'bribery')
> options = { ca_file: utils.ca_pem }
> jwt = utils.authenticate
> query = {
>     "_fields": "_id",
>     "_queryFilter": "objectClass eq 'posixAccount'",
>     "_pageSize": 5,
>     "scope": "sub"
> }
> resource = 'dc=com/dc=example/ou=People'
> hdap = Faraday.new(url: "https://#{utils.host}:#{utils.port}/hdap/", params: query, ssl: options) do |f|
>     f.headers['Content-Type'] = 'application/json'
>     f.request :authorization, 'Bearer', jwt
> end
> cookie = JSON.parse(hdap.get(resource).body, symbolize_names: true)[:pagedResultsCookie]
>
> query['_pagedResultsCookie'] = cookie
> hdap.params = query
> response = hdap.get(resource)
>
> puts "Status code: #{response.status}\nJSON: #{response.body}"
> ```
>
> Source files for this sample: [utils.rb](../_attachments/hdap/rb/utils.rb), [query-paged-next-five.rb](../_attachments/hdap/rb/query-paged-next-five.rb)
>
> HDAP Ruby examples require Ruby 3.2 and the `faraday` and `json` gems.

Notice the following features of the responses:

* `"totalPagedResultsPolicy" : "NONE"` means HDAP did not calculate the counts.

* `"remainingPagedResults" : -1` means HDAP did not count the remaining results.

  HDAP never counts `remainingPagedResults` because it would require a potentially costly calculation to determine the current position in the total result set.

* `"totalPagedResults" : -1` means HDAP did not count the total results.

When the query has the following characteristics, the response contains an estimated `totalPagedResults` count:

* The request specifies the policy using the parameter `_totalPagedResultsPolicy=ESTIMATE`.

* The `_pageSize` parameter is an integer greater than zero.

* The LDAP search for the query is indexed.

- Curl

- JavaScript

- Python

- Ruby

```console
$ curl \
 --get \
 --cacert ca-cert.pem \
 --user dc=com/dc=example/ou=People/uid=kvaughan:bribery \
 --data "_queryFilter=mail+co+'jensen'" \
 --data '_pageSize=2' \
 --data '_totalPagedResultsPolicy=ESTIMATE' \
 --data '_fields=_id' \
 --data '_prettyPrint=true' \
 --data 'scope=sub' \
 'https://localhost:8443/hdap/dc=com/dc=example/ou=People'
```

> **Collapse: Show output**
>
> ```
> {
>   "result" : [ {
>     "_id" : "dc=com/dc=example/ou=People/uid=ajensen",
>     "_rev" : "<revision>"
>   }, {
>     "_id" : "dc=com/dc=example/ou=People/uid=bjensen",
>     "_rev" : "<revision>"
>   } ],
>   "resultCount" : 2,
>   "pagedResultsCookie" : "AAAAAAAAAEI=",
>   "totalPagedResultsPolicy" : "ESTIMATE",
>   "totalPagedResults" : 7,
>   "remainingPagedResults" : -1
> }
> ```

```javascript
(async () => {
    const { authenticate, doRequest, getOptions } = require('./utils')
    const filter = "mail+co+'jensen'"
    const pageParams = '_pageSize=2&_totalPagedResultsPolicy=ESTIMATE'
    const options = getOptions({
        path: `/hdap/dc=com/dc=example/ou=People?_queryFilter=${filter}&${pageParams}&_fields=_id&scope=sub`
    })
    const jwt = await authenticate(options)
    options.headers['Authorization'] = 'Bearer ' + jwt
    const response = await doRequest('HDAP: paged query', options)
    console.log(response)
})().catch(error => { console.error(error) })
```

Source files for this sample: [query-paged.js](../_attachments/hdap/js/query-paged.js), [utils.js](../_attachments/hdap/js/utils.js)

```python
#!/usr/bin/env python3

import requests
import utils

params = {
    '_fields': '_id',
    '_queryFilter': 'mail co "jensen"',
    '_pageSize': 2,
    '_totalPagedResultsPolicy': 'ESTIMATE',
    'scope': 'sub'
}
jwt = utils.authenticate('dc=com/dc=example/ou=People/uid=kvaughan', 'bribery')
headers = { 'Content-Type': 'application/json', 'Authorization': f'Bearer {jwt}' }
response = requests.get(
    f'https://{utils.host}:{utils.port}/hdap/dc=com/dc=example/ou=People',
    headers=headers,
    params=params,
    verify=utils.ca_pem)
print('Status code: %d\nJSON: %s' % (response.status_code, response.json()))
```

Source files for this sample: [utils.py](../_attachments/hdap/py/utils.py), [query-paged.py](../_attachments/hdap/py/query-paged.py)

```ruby
require_relative 'utils.rb'
require 'faraday'

utils = Utils.new('dc=com/dc=example/ou=People/uid=kvaughan', 'bribery')
options = { ca_file: utils.ca_pem }
jwt = utils.authenticate
query = {
    "_fields": "_id",
    "_queryFilter": "mail co 'jensen'",
    "_pageSize": 2,
    "_totalPagedResultsPolicy": "ESTIMATE",
    "scope": "sub"
}
hdap = Faraday.new(url: "https://#{utils.host}:#{utils.port}/hdap/", params: query, ssl: options) do |f|
    f.headers['Content-Type'] = 'application/json'
    f.request :authorization, 'Bearer', jwt
end
response = hdap.get('dc=com/dc=example/ou=People')

puts "Status code: #{response.status}\nJSON: #{response.body}"
```

Source files for this sample: [utils.rb](../_attachments/hdap/rb/utils.rb), [query-paged.rb](../_attachments/hdap/rb/query-paged.rb)

HDAP Ruby examples require Ruby 3.2 and the `faraday` and `json` gems.

The estimated number of results can be useful, for example, when the LDAP search uses a big index or a VLV index and the total number of results is large.

## Server-side sort

Use the [`_sortKeys` parameter](rest-operations.html#query-parameters) to have HDAP sort the query results based on one or more fields in the resources.

The following example sorts results in reverse order by given name (`-givenName`):

* Curl

* JavaScript

* Python

* Ruby

```console
$ curl \
 --get \
 --cacert ca-cert.pem \
 --user dc=com/dc=example/ou=People/uid=kvaughan:bribery \
 --data "_queryFilter=sn+co+'barnes'" \
 --data '_sortKeys=-givenName' \
 --data '_fields=cn' \
 --data '_prettyPrint=true' \
 --data 'scope=sub' \
 'https://localhost:8443/hdap/dc=com/dc=example/ou=People'
```

```javascript
(async () => {
    const { authenticate, doRequest, getOptions } = require('./utils')
    const filter = "sn+co+'barnes'"
    const options = getOptions({
        path: `/hdap/dc=com/dc=example/ou=People?_queryFilter=${filter}&_sortKeys=-givenName&_fields=cn&scope=sub`
    })
    const jwt = await authenticate(options)
    options.headers['Authorization'] = 'Bearer ' + jwt
    const response = await doRequest('HDAP: query with server-side sort', options)
    console.log(response)
})().catch(error => { console.error(error) })
```

Source files for this sample: [query-sss.js](../_attachments/hdap/js/query-sss.js), [utils.js](../_attachments/hdap/js/utils.js)

```python
#!/usr/bin/env python3

import requests
import utils

params = {
    '_fields': 'cn',
    '_queryFilter': 'sn co "barnes"',
    '_sortKeys': '-givenName',
    'scope': 'sub'
}
jwt = utils.authenticate('dc=com/dc=example/ou=People/uid=kvaughan', 'bribery')
headers = { 'Content-Type': 'application/json', 'Authorization': f'Bearer {jwt}' }
response = requests.get(
    f'https://{utils.host}:{utils.port}/hdap/dc=com/dc=example/ou=People',
    headers=headers,
    params=params,
    verify=utils.ca_pem)
print('Status code: %d\nJSON: %s' % (response.status_code, response.json()))
```

Source files for this sample: [utils.py](../_attachments/hdap/py/utils.py), [query-sss.py](../_attachments/hdap/py/query-sss.py)

```ruby
require_relative 'utils.rb'
require 'faraday'

utils = Utils.new('dc=com/dc=example/ou=People/uid=kvaughan', 'bribery')
options = { ca_file: utils.ca_pem }
jwt = utils.authenticate
query = {
    "_fields": "cn",
    "_queryFilter": "sn co 'barnes'",
    "_sortKeys": "-givenName",
    "scope": "sub"
}
hdap = Faraday.new(url: "https://#{utils.host}:#{utils.port}/hdap/", params: query, ssl: options) do |f|
    f.headers['Content-Type'] = 'application/json'
    f.request :authorization, 'Bearer', jwt
end
response = hdap.get('dc=com/dc=example/ou=People')

puts "Status code: #{response.status}\nJSON: #{response.body}"
```

Source files for this sample: [utils.rb](../_attachments/hdap/rb/utils.rb), [query-sss.rb](../_attachments/hdap/rb/query-sss.rb)

HDAP Ruby examples require Ruby 3.2 and the `faraday` and `json` gems.

> **Collapse: Show results**
>
> ```json
> {
>   "result" : [ {
>     "_id" : "dc=com/dc=example/ou=People/uid=user.94561",
>     "_rev" : "<revision>",
>     "cn" : [ "Atsushi Barnes" ]
>   }, {
>     "_id" : "dc=com/dc=example/ou=People/uid=user.81142",
>     "_rev" : "<revision>",
>     "cn" : [ "Atsuo Barnes" ]
>   }, {
>     "_id" : "dc=com/dc=example/ou=People/uid=user.67723",
>     "_rev" : "<revision>",
>     "cn" : [ "Atmane Barnes" ]
>   }, {
>     "_id" : "dc=com/dc=example/ou=People/uid=user.54304",
>     "_rev" : "<revision>",
>     "cn" : [ "Atlante Barnes" ]
>   }, {
>     "_id" : "dc=com/dc=example/ou=People/uid=user.40885",
>     "_rev" : "<revision>",
>     "cn" : [ "Atlanta Barnes" ]
>   }, {
>     "_id" : "dc=com/dc=example/ou=People/uid=user.27466",
>     "_rev" : "<revision>",
>     "cn" : [ "Atl-Sales Barnes" ]
>   }, {
>     "_id" : "dc=com/dc=example/ou=People/uid=user.14047",
>     "_rev" : "<revision>",
>     "cn" : [ "Atl Barnes" ]
>   }, {
>     "_id" : "dc=com/dc=example/ou=People/uid=user.628",
>     "_rev" : "<revision>",
>     "cn" : [ "Atique Barnes" ]
>   }, {
>     "_id" : "dc=com/dc=example/ou=People/uid=abarnes",
>     "_rev" : "<revision>",
>     "cn" : [ "Anne-Louise Barnes" ]
>   } ],
>   "resultCount" : 9,
>   "pagedResultsCookie" : null,
>   "totalPagedResultsPolicy" : "NONE",
>   "totalPagedResults" : -1,
>   "remainingPagedResults" : -1
> }
> ```

* To specify multiple sort keys, use a comma-separated list of fields.

* The sort key fields you specify must exist in the result entries.

  You do not need to include the sort field(s) in the results.

* [VLV for paged server-side sort](../config-guide/idx-config.html#vlv-for-paged-sss) shows an HDAP query using a browsing index.

HDAP stores the entire result set before sorting the results. If you expect a large result set for your search, use [paged results](#query-rest-paged-results) to limit the performance cost and get results quickly.
