Query
Examples in this documentation depend on features activated in the For details, refer to Learn about the evaluation setup profile. |
To search, perform an HTTP GET with a _queryFilter=expression
parameter.
For details about the query filter expression,
refer to Query.
The |
The following table shows LDAP search filters and corresponding query filter expressions:
LDAP Filter | REST Filter |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
For details on which index to configure for a specific filter, refer to Necessary indexes.
For query operations, the filter expression is constructed from the following building blocks. Make sure you URL-encode the filter expressions, which are shown here without URL-encoding to make them easier to read.
In filter expressions, the simplest json-pointer is a field of the JSON resource,
such as userName
or id
.
A json-pointer can also point to nested elements,
as described in the JSON Pointer Internet-Draft:
- Comparison expressions
-
Build filters using the following comparison expressions:
json-pointer eq json-value
-
Matches when the pointer equals the value, as in the following example:
$ curl \ --user kvaughan:bribery \ --cacert ca-cert.pem \ --silent \ "https://localhost:8443/api/users?_queryFilter=userName+eq+'babs@example.com'&_prettyPrint=true" { "result" : [ { "_id" : "bjensen", "_rev" : "<revision>", "_schema" : "frapi:opendj:rest2ldap:posixUser:1.0", "_meta" : { "lastModified" : "<datestamp>" }, "userName" : "babs@example.com", "displayName" : [ "Barbara Jensen", "Babs Jensen" ], "name" : { "givenName" : "Barbara", "familyName" : "Jensen" }, "description" : "Original description", "manager" : { "_id" : "trigden", "_rev" : "<revision>" }, "contactInformation" : { "telephoneNumber" : "+1 408 555 9999", "emailAddress" : "babs@example.com" }, "uidNumber" : 1076, "gidNumber" : 1000, "homeDirectory" : "/home/bjensen", "groups" : [ { "_id" : "Carpoolers" } ] } ], "resultCount" : 1, "pagedResultsCookie" : null, "totalPagedResultsPolicy" : "NONE", "totalPagedResults" : -1, "remainingPagedResults" : -1 }
json-pointer co json-value
-
Matches when the pointer contains the value, as in the following example:
$ curl \ --user kvaughan:bribery \ --cacert ca-cert.pem \ --silent \ "https://localhost:8443/api/users?_queryFilter=userName+co+'jensen'&_fields=userName&_prettyPrint=true" { "result" : [ { "_id" : "ajensen", "_rev" : "<revision>", "userName" : "ajensen@example.com" }, { "_id" : "gjensen", "_rev" : "<revision>", "userName" : "gjensen@example.com" }, { "_id" : "jjensen", "_rev" : "<revision>", "userName" : "jjensen@example.com" }, { "_id" : "kjensen", "_rev" : "<revision>", "userName" : "kjensen@example.com" }, { "_id" : "rjensen", "_rev" : "<revision>", "userName" : "rjensen@example.com" }, { "_id" : "tjensen", "_rev" : "<revision>", "userName" : "tjensen@example.com" } ], "resultCount" : 6, "pagedResultsCookie" : null, "totalPagedResultsPolicy" : "NONE", "totalPagedResults" : -1, "remainingPagedResults" : -1 }
json-pointer sw json-value
-
Matches when the pointer starts with the value, as in the following example:
$ curl \ --user kvaughan:bribery \ --cacert ca-cert.pem \ --silent \ "https://localhost:8443/api/users?_queryFilter=userName+sw+'ab'&_fields=userName&_prettyPrint=true" { "result" : [ { "_id" : "abarnes", "_rev" : "<revision>", "userName" : "abarnes@example.com" }, { "_id" : "abergin", "_rev" : "<revision>", "userName" : "abergin@example.com" } ], "resultCount" : 2, "pagedResultsCookie" : null, "totalPagedResultsPolicy" : "NONE", "totalPagedResults" : -1, "remainingPagedResults" : -1 }
json-pointer lt json-value
-
Matches when the pointer is less than the value, as in the following example:
$ curl \ --user admin:password \ --cacert ca-cert.pem \ --silent \ "https://localhost:8443/api/users?_queryFilter=userName+lt+'ac'&_fields=userName&_prettyPrint=true" { "result" : [ { "_id" : "abarnes", "_rev" : "<revision>", "userName" : "abarnes@example.com" }, { "_id" : "abergin", "_rev" : "<revision>", "userName" : "abergin@example.com" } ], "resultCount" : 2, "pagedResultsCookie" : null, "totalPagedResultsPolicy" : "NONE", "totalPagedResults" : -1, "remainingPagedResults" : -1 }
json-pointer le json-value
-
Matches when the pointer is less than or equal to the value, as in the following example:
$ curl \ --user admin:password \ --cacert ca-cert.pem \ --silent \ "https://localhost:8443/api/users?_queryFilter=userName+le+'ad'&_fields=userName&_prettyPrint=true" { "result" : [ { "_id" : "abarnes", "_rev" : "<revision>", "userName" : "abarnes@example.com" }, { "_id" : "abergin", "_rev" : "<revision>", "userName" : "abergin@example.com" }, { "_id" : "achassin", "_rev" : "<revision>", "userName" : "achassin@example.com" } ], "resultCount" : 3, "pagedResultsCookie" : null, "totalPagedResultsPolicy" : "NONE", "totalPagedResults" : -1, "remainingPagedResults" : -1 }
json-pointer gt json-value
-
Matches when the pointer is greater than the value, as in the following example:
$ curl \ --user admin:password \ --cacert ca-cert.pem \ --silent \ "https://localhost:8443/api/users?_queryFilter=userName+gt+'wa'&_fields=userName&_prettyPrint=true" { "result" : [ { "_id" : "wlutz", "_rev" : "<revision>", "userName" : "wlutz@example.com" } ], "resultCount" : 1, "pagedResultsCookie" : null, "totalPagedResultsPolicy" : "NONE", "totalPagedResults" : -1, "remainingPagedResults" : -1 }
json-pointer ge json-value
-
Matches when the pointer is greater than or equal to the value, as in the following example:
$ curl \ --user admin:password \ --cacert ca-cert.pem \ --silent \ "https://localhost:8443/api/users?_queryFilter=userName+ge+'va'&_fields=userName&_prettyPrint=true" { "result" : [ { "_id" : "wlutz", "_rev" : "<revision>", "userName" : "wlutz@example.com" } ], "resultCount" : 1, "pagedResultsCookie" : null, "totalPagedResultsPolicy" : "NONE", "totalPagedResults" : -1, "remainingPagedResults" : -1 }
- Presence expression
-
json-pointer pr
matches any resource on which the json-pointer is present:$ curl \ --user kvaughan:bribery \ --cacert ca-cert.pem \ --silent \ "https://localhost:8443/api/groups?_queryFilter=displayName+pr&_fields=displayName&_prettyPrint=true" { "result" : [ { "_id" : "Accounting Managers", "_rev" : "<revision>", "displayName" : "Accounting Managers" }, { "_id" : "Directory Administrators", "_rev" : "<revision>", "displayName" : "Directory Administrators" }, { "_id" : "HR Managers", "_rev" : "<revision>", "displayName" : "HR Managers" }, { "_id" : "PD Managers", "_rev" : "<revision>", "displayName" : "PD Managers" }, { "_id" : "QA Managers", "_rev" : "<revision>", "displayName" : "QA Managers" } ], "resultCount" : 5, "pagedResultsCookie" : null, "totalPagedResultsPolicy" : "NONE", "totalPagedResults" : -1, "remainingPagedResults" : -1 }
- Literal expressions
-
true
matches any resource in the collection.false
matches no resource in the collection.In other words, you can list all resources in a collection as in the following example:
$ curl \ --user kvaughan:bribery \ --cacert ca-cert.pem \ --silent \ "https://localhost:8443/api/groups?_queryFilter=true&_fields=_id&_prettyPrint=true" { "result" : [ { "_id" : "Accounting Managers", "_rev" : "<revision>" }, { "_id" : "Directory Administrators", "_rev" : "<revision>" }, { "_id" : "HR Managers", "_rev" : "<revision>" }, { "_id" : "PD Managers", "_rev" : "<revision>" }, { "_id" : "QA Managers", "_rev" : "<revision>" } ], "resultCount" : 5, "pagedResultsCookie" : null, "totalPagedResultsPolicy" : "NONE", "totalPagedResults" : -1, "remainingPagedResults" : -1 }
- Complex expressions
-
Combine expressions using boolean operators
and
,or
, and!
(not), and by using parentheses(expression)
with group expressions. The following example queries resources with last name Jensen and manager name starting withSam
:$ curl \ --user kvaughan:bribery \ --cacert ca-cert.pem \ --silent \ "https://localhost:8443/api/users?_queryFilter=\ (name/familyName+co+'jensen'+and+manager/displayName+sw+'Sam')&_fields=name/familyName,manager/displayName&_prettyPrint=true" { "result" : [ { "_id" : "bjense2", "_rev" : "<revision>", "name" : { "familyName" : "Jensen" }, "manager" : { "displayName" : [ "Sam Carter", "Samantha Carter" ], "_id" : "scarter", "_rev" : "<revision>" } }, { "_id" : "jjensen", "_rev" : "<revision>", "name" : { "familyName" : "Jensen" }, "manager" : { "displayName" : [ "Sam Carter", "Samantha Carter" ], "_id" : "scarter", "_rev" : "<revision>" } }, { "_id" : "tjensen", "_rev" : "<revision>", "name" : { "familyName" : "Jensen" }, "manager" : { "displayName" : [ "Sam Carter", "Samantha Carter" ], "_id" : "scarter", "_rev" : "<revision>" } } ], "resultCount" : 3, "pagedResultsCookie" : null, "totalPagedResultsPolicy" : "NONE", "totalPagedResults" : -1, "remainingPagedResults" : -1 }
Notice the filters use the JSON pointers
name/familyName
andmanager/displayName
to identify the fields nested inside thename
andmanager
objects.
Graph-like queries
The default REST to LDAP sample mapping defines references with resourcePath
fields.
When the REST to LDAP mapping defines references to other resources in this way, the mapping supports recursion.
Client applications can use query filters that traverse a "graph" of resources.
The following example gets users whose manager belongs to the Directory Administrators
group.
The search is not indexed by default, so the directory superuser makes the request:
$ curl \
--user admin:password \
--cacert ca-cert.pem \
--silent \
"https://localhost:8443/api/users/?_queryFilter=/manager/groups/_id+eq+'Directory%20Administrators'&_fields=_id&_prettyPrint=true"
{
"result" : [ {
"_id" : "ashelton",
"_rev" : "<revision>"
}, {
"_id" : "btalbot",
"_rev" : "<revision>"
}, {
"_id" : "dakers",
"_rev" : "<revision>"
}, {
"_id" : "dsmith",
"_rev" : "<revision>"
}, {
"_id" : "eward",
"_rev" : "<revision>"
}, {
"_id" : "gjensen",
"_rev" : "<revision>"
}, {
"_id" : "hmiller",
"_rev" : "<revision>"
}, {
"_id" : "jburrell",
"_rev" : "<revision>"
}, {
"_id" : "jcampai2",
"_rev" : "<revision>"
}, {
"_id" : "jfalena",
"_rev" : "<revision>"
}, {
"_id" : "jvaughan",
"_rev" : "<revision>"
}, {
"_id" : "kcarter",
"_rev" : "<revision>"
}, {
"_id" : "mreuter",
"_rev" : "<revision>"
}, {
"_id" : "newuser",
"_rev" : "<revision>"
}, {
"_id" : "pworrell",
"_rev" : "<revision>"
}, {
"_id" : "rbannist",
"_rev" : "<revision>"
}, {
"_id" : "rdaugherty",
"_rev" : "<revision>"
}, {
"_id" : "rschneid",
"_rev" : "<revision>"
}, {
"_id" : "striplet",
"_rev" : "<revision>"
}, {
"_id" : "tclow",
"_rev" : "<revision>"
}, {
"_id" : "tmason",
"_rev" : "<revision>"
}, {
"_id" : "tschmith",
"_rev" : "<revision>"
}, {
"_id" : "tward",
"_rev" : "<revision>"
} ],
"resultCount" : 23,
"pagedResultsCookie" : null,
"totalPagedResultsPolicy" : "NONE",
"totalPagedResults" : -1,
"remainingPagedResults" : -1
}
REST to LDAP translates such graph-like HTTP queries into a series of corresponding LDAP requests. Complex graph-like queries can have a significant server-side performance impact.
Complex JSON queries
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}]}
.
To try this feature:
-
Install a DS server with the
ds-evaluation
setup profile. -
Replace the
"frapi:opendj:rest2ldap:posixUser:1.0"
resource type definition with a resource type for a user with ajson
attribute in the mapping configuration file,/path/to/opendj/config/rest2ldap/endpoints/api/example-v1.json
:// A user with a "json" attribute. "frapi:opendj:rest2ldap:jsonUser:1.0": { "superType": "frapi:opendj:rest2ldap:user:1.0", "objectClasses": [ "jsonObject" ], "properties": { "json": { "type": "json", "isMultiValued": true } } },
Alternatively, download jsonUser.json to replace the existing file.
-
Restart DS to load the new API configuration.
-
Perform searches using the configuration.
This search finds an entry with a
json
attribute that has an "array" field containing an array of objects:$ curl \ --user kvaughan:bribery \ --cacert ca-cert.pem \ --silent \ --get \ --data-urlencode "_queryFilter=json/array[x eq 1] and json/array[y eq 4]" \ --data-urlencode "_fields=json" \ --data-urlencode "_prettyPrint=true" \ "https://localhost:8443/api/users/" { "result" : [ { "_id" : "abarnes", "_rev" : "<revision>", "json" : [ { "array" : [ { "x" : 1, "y" : 2 }, { "x" : 3, "y" : 4 } ] } ] } ], "resultCount" : 1, "pagedResultsCookie" : null, "totalPagedResultsPolicy" : "NONE", "totalPagedResults" : -1, "remainingPagedResults" : -1 }
-
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}
.
-
Paged results
You can page through search results using the following query string parameters that are further described in Query:
-
_pagedResultsCookie=string
-
_pagedResultsOffset=integer
-
_pageSize=integer
The following example demonstrates how paged results are used:
# Request five results per page, and retrieve the first page:
$ curl \
--user admin:password \
--cacert ca-cert.pem \
--silent \
"https://localhost:8443/api/users?_queryFilter=true&_fields=userName&_pageSize=5&_prettyPrint=true"
{
"result" : [ {
"_id" : "abarnes",
"_rev" : "<revision>",
"userName" : "abarnes@example.com"
}, {
"_id" : "abergin",
"_rev" : "<revision>",
"userName" : "abergin@example.com"
}, {
"_id" : "achassin",
"_rev" : "<revision>",
"userName" : "achassin@example.com"
}, {
"_id" : "ahall",
"_rev" : "<revision>",
"userName" : "ahall@example.com"
}, {
"_id" : "ahel",
"_rev" : "<revision>",
"userName" : "ahel@example.com"
} ],
"resultCount" : 5,
"pagedResultsCookie" : "<cookie>",
"totalPagedResultsPolicy" : "NONE",
"totalPagedResults" : -1,
"remainingPagedResults" : -1
}
$ export COOKIE=$(cut -d \" -f 4 <(grep pagedResultsCookie \
<(curl --cacert ca-cert.pem \
--user admin:password \
--silent \
"https://localhost:8443/api/users?_queryFilter=true&_fields=userName&_pageSize=5&_prettyPrint=true")))
# Provide the cookie to request the next five results:
$ curl \
--user admin:password \
--cacert ca-cert.pem \
--silent \
"https://localhost:8443/api/users?_queryFilter=true&_fields=userName&_pageSize=5\
&_pagedResultsCookie=$COOKIE&_prettyPrint=true"
{
"result" : [ {
"_id" : "ahunter",
"_rev" : "<revision>",
"userName" : "ahunter@example.com"
}, {
"_id" : "ajensen",
"_rev" : "<revision>",
"userName" : "ajensen@example.com"
}, {
"_id" : "aknutson",
"_rev" : "<revision>",
"userName" : "aknutson@example.com"
}, {
"_id" : "alangdon",
"_rev" : "<revision>",
"userName" : "alangdon@example.com"
}, {
"_id" : "alutz",
"_rev" : "<revision>",
"userName" : "alutz@example.com"
} ],
"resultCount" : 5,
"pagedResultsCookie" : "<new-cookie>",
"totalPagedResultsPolicy" : "NONE",
"totalPagedResults" : -1,
"remainingPagedResults" : -1
}
# Request the tenth page of five results:
$ curl \
--user admin:password \
--cacert ca-cert.pem \
--silent \
"https://localhost:8443/api/users?_queryFilter=true&_fields=userName\
&_pageSize=5&_pagedResultsOffset=10&_prettyPrint=true"
{
"result" : [ {
"_id" : "ashelton",
"_rev" : "<revision>",
"userName" : "ashelton@example.com"
}, {
"_id" : "awalker",
"_rev" : "<revision>",
"userName" : "awalker@example.com"
}, {
"_id" : "awhite",
"_rev" : "<revision>",
"userName" : "awhite@example.com"
}, {
"_id" : "aworrell",
"_rev" : "<revision>",
"userName" : "aworrell@example.com"
}, {
"_id" : "bfrancis",
"_rev" : "<revision>",
"userName" : "bfrancis@example.com"
} ],
"resultCount" : 5,
"pagedResultsCookie" : "<cookie>",
"totalPagedResultsPolicy" : "NONE",
"totalPagedResults" : -1,
"remainingPagedResults" : -1
}
The LDAP searches corresponding to the queries in these examples are not indexed. Notice the following features of the responses:
-
"remainingPagedResults" : -1
means that the number of remaining results is not calculated. -
"totalPagedResults" : -1
means that the total number of paged results is not calculated. -
"totalPagedResultsPolicy" : "NONE"
means that result counting is disabled.
When the query has the following characteristics, the response contains an estimated number of "totalPagedResults"
:
-
The request specifies the policy using the parameter
_totalPagedResultsPolicy=ESTIMATE
. -
The request sets the
_pageSize
parameter to an integer greater than zero. -
The LDAP search for the query is indexed.
For example:
$ curl \
--user kvaughan:bribery \
--cacert ca-cert.pem \
--silent \
"https://localhost:8443/api/users?_queryFilter=userName+co+'jensen'&_pageSize=2&_totalPagedResultsPolicy=ESTIMATE&_fields=displayName&_prettyPrint=true"
{
"result" : [ {
"_id" : "ajensen",
"_rev" : "<revision>",
"displayName" : [ "Allison Jensen" ]
}, {
"_id" : "gjensen",
"_rev" : "<revision>",
"displayName" : [ "Gern Jensen" ]
} ],
"resultCount" : 2,
"pagedResultsCookie" : "<cookie>",
"totalPagedResultsPolicy" : "ESTIMATE",
"totalPagedResults" : 6,
"remainingPagedResults" : -1
}
Notice that "remainingPagedResults" : -1
in this case, too.
REST to LDAP never calculates the value for this field,
as doing so would require a potentially costly calculation to determine the current position in the total result set.
The estimated number of results can be useful when the LDAP search uses a big index or a VLV index, and the total number of results is large.
Server-side sort
You can use the _sortKeys
parameter, described in Query,
to request that the server sort the results it returns.
The following example sorts results by given name:
$ curl \
--user admin:password \
--cacert ca-cert.pem \
--silent \
"https://localhost:8443/api/users?_queryFilter=name/familyName+eq+'jensen'\
&_sortKeys=name/givenName&_fields=name&_prettyPrint=true"
{
"result" : [ {
"_id" : "ajensen",
"_rev" : "<revision>",
"name" : {
"givenName" : "Allison",
"familyName" : "Jensen"
}
}, {
"_id" : "bjensen",
"_rev" : "<revision>",
"name" : {
"givenName" : "Barbara",
"familyName" : "Jensen"
}
}, {
"_id" : "bjense2",
"_rev" : "<revision>",
"name" : {
"givenName" : "Bjorn",
"familyName" : "Jensen"
}
}, {
"_id" : "gjensen",
"_rev" : "<revision>",
"name" : {
"givenName" : "Gern",
"familyName" : "Jensen"
}
}, {
"_id" : "jjensen",
"_rev" : "<revision>",
"name" : {
"givenName" : "Jody",
"familyName" : "Jensen"
}
}, {
"_id" : "kjensen",
"_rev" : "<revision>",
"name" : {
"givenName" : "Kurt",
"familyName" : "Jensen"
}
}, {
"_id" : "user.5814",
"_rev" : "<revision>",
"name" : {
"givenName" : "Mollie",
"familyName" : "Jensen"
}
}, {
"_id" : "user.19233",
"_rev" : "<revision>",
"name" : {
"givenName" : "Molly",
"familyName" : "Jensen"
}
}, {
"_id" : "user.32652",
"_rev" : "<revision>",
"name" : {
"givenName" : "Mommy",
"familyName" : "Jensen"
}
}, {
"_id" : "user.46071",
"_rev" : "<revision>",
"name" : {
"givenName" : "Mona",
"familyName" : "Jensen"
}
}, {
"_id" : "user.59490",
"_rev" : "<revision>",
"name" : {
"givenName" : "Monah",
"familyName" : "Jensen"
}
}, {
"_id" : "user.72909",
"_rev" : "<revision>",
"name" : {
"givenName" : "Monica",
"familyName" : "Jensen"
}
}, {
"_id" : "user.86328",
"_rev" : "<revision>",
"name" : {
"givenName" : "Moniek",
"familyName" : "Jensen"
}
}, {
"_id" : "user.99747",
"_rev" : "<revision>",
"name" : {
"givenName" : "Monika",
"familyName" : "Jensen"
}
}, {
"_id" : "rjense2",
"_rev" : "<revision>",
"name" : {
"givenName" : "Randy",
"familyName" : "Jensen"
}
}, {
"_id" : "rjensen",
"_rev" : "<revision>",
"name" : {
"givenName" : "Richard",
"familyName" : "Jensen"
}
}, {
"_id" : "tjensen",
"_rev" : "<revision>",
"name" : {
"givenName" : "Ted",
"familyName" : "Jensen"
}
} ],
"resultCount" : 17,
"pagedResultsCookie" : null,
"totalPagedResultsPolicy" : "NONE",
"totalPagedResults" : -1,
"remainingPagedResults" : -1
}
To sort in reverse order, use _sortKeys=-field
.
To specify multiple sort keys, use a comma-separated list of fields.
The sort key fields that you specify must exist in the result entries.
The server must store and then sort the result set for your search. If you expect a large result set for your search, use paged results, described in Paged results, to limit the impact on the server and get your results more quickly.