Identity and Context Starter Pack
Who is actually running this, what they're allowed to do, and where it's happening
Every sample here answers one blunt question: who, exactly, is running this - and what does that identity actually let them do? No vibes, no assumptions. Just the raw output sitting right next to the code that produced it.
This pack is for those "works on my machine" moments when the user, role, privilege, server, or host is not what you expect. The examples keep the focus on the metadata that matters most when a query behaves differently from the way it looked in development: the name-to-ID lookups that turn a raw numeric ID in a log line back into something you can act on, the privilege and default-security checks that explain what a user or role can actually do, and the external security and login history that explain where a set of credentials came from in the first place.
The examples in this article assume the llamaverse (v2.0+) is deployed. The llamaverse sample data is freely available from github.com/cleverllamas/llamaverse - see the llamaverse article for full setup instructions.
API Context for This Pack
| Context Item | What this pack uses |
|---|---|
| Data set | llamaverse v2.0+ sample data (used as execution-context backdrop) |
| Primary focus | runtime identity, name/ID resolution, privilege checks, default security, external security, and server/host context |
| Views used | None |
| Fields used | None |
| Index context | Not index-dependent; results are derived from current execution security, server, and host state |
If output changes between runs, verify the credentials, execute privilege context, and app server endpoint are the same.
Current Execution Identity
Who is actually running this request, and what can they see? Everything else in this pack only makes sense once you've answered that.
xdmp:get-current-user
Step one of debugging permissions is admitting who you really are.
Source docs: https://docs.marklogic.com/11.0/xdmp:get-current-user
| Option / Argument | What it controls | Used here |
|---|---|---|
| None | Returns current execution user name | Read directly from current security context |
xquery version "1.0-ml";
(
"current-user",
xdmp:get-current-user(),
"sample-llamaverse-count",
xdmp:estimate(collection("wild-llamas"))
)
'use strict';
// Get the current user and a sample collection estimate.
const currentUser = xdmp.getCurrentUser();
const llamaverseEstimate = cts.estimate(cts.collectionQuery('wild-llamas'));
Sequence.from([
'current-user', currentUser,
'sample-llamaverse-count', llamaverseEstimate
]);
current-user
admin
sample-llamaverse-count
4561
| Line | Value |
|---|---|
| 1 | current-user |
| 2 | admin |
| 3 | sample-llamaverse-count |
| 4 | 4561 |
What to notice: pairing identity with a visibility check like this is a debugging habit worth stealing - know who you are, then prove what you can actually see. Skip the second half and you're just trusting the badge on the door.
xdmp:get-current-roles
The role list that explains most surprises in query behaviour.
Source docs: https://docs.marklogic.com/11.0/xdmp:get-current-roles
| Option / Argument | What it controls | Used here |
|---|---|---|
| None | Returns role IDs granted to the current execution user | Mapped to role names in sample output |
xquery version "1.0-ml";
for $role-id in xdmp:get-current-roles()
let $role-name := xdmp:role-name($role-id)
order by $role-name
return map:entry("role-id", $role-id) => map:with("role-name", $role-name)
'use strict';
// Get current roles and their names.
const roleIds = xdmp.getCurrentRoles().toArray();
const roles = roleIds
.map(roleId => ({
roleId: roleId,
roleName: xdmp.roleName(roleId)
}))
.sort((a, b) => a.roleName.localeCompare(b.roleName));
roles;
{"role-id": "8487823278258687528", "role-name": "admin"}
[{"roleId":"8487823278258687528", "roleName":"admin"}]
| role-id | role-name |
|---|---|
| 8487823278258687528 | admin |
What to notice: a raw role ID means nothing to a human mid-incident - mapping it to a name is what turns a security log from noise into an answer. The shape differs slightly between languages: XQuery returns a single map with role-id/role-name keys because this admin user has one role, while the JavaScript sample returns an array of roleId/roleName objects (JavaScript's usual camelCase convention), so the same code still holds up for users with several roles.
Name and ID Resolution
MarkLogic's security model runs on numeric IDs internally — names are a convenience layer on top. These four functions convert between names and IDs in both directions, for both users and roles, so a raw ID in a log line or an error message can be turned back into something a person can act on.
xdmp:user
Turn a user name into an ID before you compare it against a permission or an audit entry.
Source docs: https://docs.marklogic.com/11.0/xdmp:user
| Option / Argument | What it controls | Used here |
|---|---|---|
$user | User name to resolve to a user ID | Current execution user name |
$extSecId (optional) | External security config ID to search — only needed to resolve an external user; defaults to the current App Server's external-security setting | Not supplied — internal user lookup |
$secDbFirst (optional) | Whether to check the security database before any specified external security; defaults to the App Server's internal-security setting (true when running on the task server) | Not supplied — default behaviour |
xquery version "1.0-ml";
let $user-name := xdmp:get-current-user()
return
(
"user-name", $user-name,
"user-id", xdmp:user($user-name)
)
'use strict';
// Resolve a user name to its user ID.
const userName = xdmp.getCurrentUser();
const userId = xdmp.user(userName);
Sequence.from([
'user-name', userName,
'user-id', userId
]);
user-name
admin
user-id
7071164303237443533
| Line | Value |
|---|---|
| 1 | user-name |
| 2 | admin |
| 3 | user-id |
| 4 | 7071164303237443533 |
What to notice: user IDs are what permissions and audit records actually store — resolving a name to an ID lets a script assert identity precisely instead of comparing strings.
xdmp:user-roles
Every role a named user holds, direct or inherited — not just the roles active in the current execution context.
Source docs: https://docs.marklogic.com/11.0/xdmp:user-roles
| Option / Argument | What it controls | Used here |
|---|---|---|
$name | User name whose full role set is requested | Current execution user name |
$extSecId (optional) | External security config ID to search — only needed to resolve an external user; defaults to the current App Server's external-security setting | Not supplied — internal user lookup |
$secDbFirst (optional) | Whether to check the security database before any specified external security; defaults to the App Server's internal-security setting (true when running on the task server) | Not supplied — default behaviour |
xquery version "1.0-ml";
let $user-name := xdmp:get-current-user()
for $role-id in xdmp:user-roles($user-name)
let $role-name := xdmp:role-name($role-id)
order by $role-name
return map:entry("role-id", $role-id) => map:with("role-name", $role-name)
'use strict';
// List every role granted to a named user, direct or inherited.
const userName = xdmp.getCurrentUser();
const roleIds = xdmp.userRoles(userName).toArray();
const roles = roleIds
.map(roleId => ({
roleId: roleId,
roleName: xdmp.roleName(roleId)
}))
.sort((a, b) => a.roleName.localeCompare(b.roleName));
roles;
{"role-id": "8487823278258687528", "role-name": "admin"}
[{"roleId":"8487823278258687528", "roleName":"admin"}]
| role-id | role-name |
|---|---|
| 8487823278258687528 | admin |
What to notice: xdmp:user-roles takes a user name and works for any user on the system, while xdmp:get-current-roles only reports the roles active for whoever is running the current request. They can differ — a user's full role set includes roles inherited through role composition, which is not always the same as what is active in a given execution context.
xdmp:role
Turn a role name into an ID, the same way xdmp:user does for user names.
Source docs: https://docs.marklogic.com/11.0/xdmp:role
| Option / Argument | What it controls | Used here |
|---|---|---|
$role | Role name to resolve to a role ID | admin |
xquery version "1.0-ml";
(
"role-name", "admin",
"role-id", xdmp:role("admin")
)
'use strict';
// Resolve a role name to its role ID.
const roleName = 'admin';
const roleId = xdmp.role(roleName);
Sequence.from([
'role-name', roleName,
'role-id', roleId
]);
role-name
admin
role-id
8487823278258687528
| Line | Value |
|---|---|
| 1 | role-name |
| 2 | admin |
| 3 | role-id |
| 4 | 8487823278258687528 |
What to notice: the ID returned here matches the one xdmp:get-current-roles reported earlier for this user - confirming both functions are describing the exact same role, not two different flavours of "admin".
xdmp:role-name
The reverse lookup — turn a role ID back into a name for logs and reports.
Source docs: https://docs.marklogic.com/11.0/xdmp:role-name
| Option / Argument | What it controls | Used here |
|---|---|---|
$role-id | Role ID to resolve back to a role name | ID resolved by xdmp:role(...) |
xquery version "1.0-ml";
let $role-id := xdmp:role("admin")
return
(
"role-id", $role-id,
"role-name", xdmp:role-name($role-id)
)
'use strict';
// Resolve a role ID back to its role name.
const roleId = xdmp.role('admin');
const roleName = xdmp.roleName(roleId);
Sequence.from([
'role-id', roleId,
'role-name', roleName
]);
role-id
8487823278258687528
role-name
admin
| Line | Value |
|---|---|
| 1 | role-id |
| 2 | 8487823278258687528 |
| 3 | role-name |
| 4 | admin |
What to notice: this is the same round trip as xdmp:database/xdmp:database-name in the Database and Environment Starter Pack — resolve to an ID to assert identity, resolve back to a name to keep output readable.
Privileges
Knowing who a user or role is only answers half the question — knowing what they are actually allowed to do is the other half. These three functions test and list execute and URI privileges directly, rather than inferring them from role membership.
xdmp:has-privilege
The direct yes/no check: does the current user hold at least one of a given set of privileges. This is the function application code actually calls to gate a feature — the other two functions in this section are for auditing, not runtime checks.
Source docs: https://docs.marklogic.com/11.0/xdmp:has-privilege
| Option / Argument | What it controls | Used here |
|---|---|---|
$privileges | Set of privilege URIs to check — these are privilege URIs, not privilege names | http://marklogic.com/xdmp/privileges/xdmp-eval |
$kind | Kind of privilege to check: execute or uri | execute |
xquery version "1.0-ml";
let $privilege := "http://marklogic.com/xdmp/privileges/xdmp-eval"
return
(
"privilege", $privilege,
"has-privilege", xdmp:has-privilege($privilege, "execute")
)
'use strict';
// Check whether the current user holds a specific execute privilege.
const privilege = 'http://marklogic.com/xdmp/privileges/xdmp-eval';
const hasPrivilege = xdmp.hasPrivilege(privilege, 'execute');
Sequence.from([
'privilege', privilege,
'has-privilege', hasPrivilege
]);
privilege
http://marklogic.com/xdmp/privileges/xdmp-eval
has-privilege
true
| Line | Value |
|---|---|
| 1 | privilege |
| 2 | http://marklogic.com/xdmp/privileges/xdmp-eval |
| 3 | has-privilege |
| 4 | true |
What to notice: admin holds the xdmp-eval execute privilege by default, which is exactly why every other sample in this article is able to run. Check "uri" instead of "execute" when the privilege in question gates a document URI rather than a function call.
xdmp:user-privileges
Every privilege ID directly granted to a named user — execute and URI privileges combined, not filtered by kind. Requires the http://marklogic.com/xdmp/privileges/xdmp-user-privileges execute privilege to call.
Source docs: https://docs.marklogic.com/11.0/xdmp:user-privileges
| Option / Argument | What it controls | Used here |
|---|---|---|
$user | User name whose granted privilege IDs are requested | Current execution user name |
$extSecId (optional) | External security config ID to search for an external user | Not supplied |
$secDbFirst (optional) | Whether to check the security database before any specified external security | Not supplied |
xquery version "1.0-ml";
let $user-name := xdmp:get-current-user()
let $privilege-ids := xdmp:user-privileges($user-name)
return
(
"user-name", $user-name,
"privilege-count", fn:count($privilege-ids)
)
'use strict';
// Count every privilege (execute and URI) granted to a named user.
const userName = xdmp.getCurrentUser();
const privilegeIds = xdmp.userPrivileges(userName).toArray();
Sequence.from([
'user-name', userName,
'privilege-count', privilegeIds.length
]);
user-name
admin
privilege-count
18
| Line | Value |
|---|---|
| 1 | user-name |
| 2 | admin |
| 3 | privilege-count |
| 4 | 18 |
What to notice: the return value is a sequence of raw privilege IDs, not names — there is no xdmp:privilege-name built-in. Turning an ID into something readable means querying the Security database directly (sec:get-privilege and similar), which is outside the scope of a content-database probe like this one. The count on its own is still useful: a sudden drop after a role change is a fast signal that something was revoked.
xdmp:role-privileges
The same privilege listing as xdmp:user-privileges, scoped to a role ID instead of a user name — the set of privileges attached directly to the role, before role composition pulls in anything from parent roles. Requires the http://marklogic.com/xdmp/privileges/xdmp-role-privileges execute privilege to call.
Source docs: https://docs.marklogic.com/11.0/xdmp:role-privileges
| Option / Argument | What it controls | Used here |
|---|---|---|
$roleId | Role ID whose directly granted privilege IDs are requested | ID resolved by xdmp:role("admin") |
xquery version "1.0-ml";
let $role-name := "admin"
let $role-id := xdmp:role($role-name)
let $privilege-ids := xdmp:role-privileges($role-id)
return
(
"role-name", $role-name,
"role-id", $role-id,
"privilege-count", fn:count($privilege-ids)
)
'use strict';
// Count the privileges (execute and URI) granted directly to a role.
const roleName = 'admin';
const roleId = xdmp.role(roleName);
const privilegeIds = xdmp.rolePrivileges(roleId).toArray();
Sequence.from([
'role-name', roleName,
'role-id', roleId,
'privilege-count', privilegeIds.length
]);
role-name
admin
role-id
8487823278258687528
privilege-count
18
| Line | Value |
|---|---|
| 1 | role-name |
| 2 | admin |
| 3 | role-id |
| 4 | 8487823278258687528 |
| 5 | privilege-count |
| 6 | 18 |
What to notice: the admin user and the admin role report the same privilege count here because this user's only role is admin — for a user holding several roles, xdmp:user-privileges reports the union across all of them while xdmp:role-privileges reports one role at a time.
Default Collections and Permissions
When a document is inserted without explicit collections or permissions, MarkLogic falls back to defaults resolved from the inserting user's security profile and the roles that user holds. These six functions surface those defaults directly, so "why did my document end up in that collection" or "why can that role read this" stops being a guess.
xdmp:default-collections
The collections a new document would receive right now, for the current execution user, if inserted without specifying any.
Source docs: https://docs.marklogic.com/11.0/xdmp:default-collections
| Option / Argument | What it controls | Used here |
|---|---|---|
$uri (optional) | Document URI used to resolve directory-level default collections | Not supplied — current user context only |
xquery version "1.0-ml";
xdmp:default-collections()
'use strict';
// Collections a new document would get right now, with no collections specified.
xdmp.defaultCollections();
(empty sequence — admin has no default collections configured)
What to notice: an empty result here is normal, not broken — admin has no default collections configured on this system, so a document inserted without an explicit collections option would simply get none. Where directory-level default collections are configured on a parent directory, supply $uri to see the collections that specific insert would inherit.
xdmp:default-permissions
The permissions a new document would receive right now, for the current execution user, if inserted without specifying any.
Source docs: https://docs.marklogic.com/11.0/xdmp:default-permissions
| Option / Argument | What it controls | Used here |
|---|---|---|
$uri (optional) | Document URI used to resolve directory-level default permissions | Not supplied — current user context only |
$output-kind (optional) | elements (default) for sec:permission XML, or objects for map:map/JSON | objects |
xquery version "1.0-ml";
xdmp:default-permissions((), "objects")
'use strict';
// Permissions a new document would get right now, with no permissions specified.
xdmp.defaultPermissions(null, 'objects');
(empty sequence — admin has no default permissions configured)
[]
What to notice: XQuery and JavaScript disagree on how to represent "nothing" here, and it is worth knowing before it surprises you in production code. An empty XQuery sequence produces no output at all, while the JavaScript binding for "objects" output returns an actual (empty) array — [] — rather than an empty Sequence. Test for permissions.length === 0 in JavaScript rather than assuming a falsy or undefined result.
xdmp:user-get-default-collections
The default collections configured directly on a named user's security profile — a stored setting, distinct from xdmp:default-collections, which reports the resolved outcome for whoever is currently running the request.
Source docs: https://docs.marklogic.com/11.0/xdmp:user-get-default-collections
| Option / Argument | What it controls | Used here |
|---|---|---|
$username | User name whose configured default collections are requested | Current execution user name |
xquery version "1.0-ml";
let $user-name := xdmp:get-current-user()
return xdmp:user-get-default-collections($user-name)
'use strict';
// Default collections configured on a named user's security profile.
const userName = xdmp.getCurrentUser();
xdmp.userGetDefaultCollections(userName);
(empty sequence — admin has no default collections configured)
What to notice: this reads the setting stored on the user record itself, for any named user — not just the one running the current request, which is the distinction that makes it useful for auditing security configuration rather than debugging a single execution.
xdmp:user-get-default-permissions
The default permissions configured directly on a named user's security profile.
Source docs: https://docs.marklogic.com/11.0/xdmp:user-get-default-permissions
| Option / Argument | What it controls | Used here |
|---|---|---|
$username | User name whose configured default permissions are requested | Current execution user name |
$output-kind (optional) | elements (default) for sec:permission XML, or objects for map:map/JSON | objects |
xquery version "1.0-ml";
let $user-name := xdmp:get-current-user()
return xdmp:user-get-default-permissions($user-name, "objects")
'use strict';
// Default permissions configured on a named user's security profile.
const userName = xdmp.getCurrentUser();
xdmp.userGetDefaultPermissions(userName, 'objects');
(empty sequence — admin has no default permissions configured)
[]
What to notice: same empty-sequence-versus-empty-array behaviour as xdmp:default-permissions above, and the same user-record-versus-resolved-outcome distinction as xdmp:user-get-default-collections.
xdmp:role-get-default-collections
The default collections configured directly on a named role's security profile — these apply to any user holding the role, in addition to whatever that user's own profile configures.
Source docs: https://docs.marklogic.com/11.0/xdmp:role-get-default-collections
| Option / Argument | What it controls | Used here |
|---|---|---|
$rolename | Role name whose configured default collections are requested | admin |
xquery version "1.0-ml";
xdmp:role-get-default-collections("admin")
'use strict';
// Default collections configured directly on a role's security profile.
xdmp.roleGetDefaultCollections('admin');
(empty sequence — the admin role has no default collections configured)
What to notice: the xdmp:user-get-* and xdmp:role-get-* functions in this section mirror each other exactly — the only difference is whether the security profile being inspected belongs to a user or a role.
xdmp:role-get-default-permissions
The default permissions configured directly on a named role's security profile.
Source docs: https://docs.marklogic.com/11.0/xdmp:role-get-default-permissions
| Option / Argument | What it controls | Used here |
|---|---|---|
$rolename | Role name whose configured default permissions are requested | admin |
$output-kind (optional) | elements (default) for sec:permission XML, or objects for map:map/JSON | objects |
xquery version "1.0-ml";
xdmp:role-get-default-permissions("admin", "objects")
'use strict';
// Default permissions configured directly on a role's security profile.
xdmp.roleGetDefaultPermissions('admin', 'objects');
(empty sequence — the admin role has no default permissions configured)
[]
What to notice: an empty result across all six functions in this section reflects a system with no custom default security configured — the moment any of these come back non-empty in your own environment, you have found exactly where a document's collections or permissions are coming from by default.
External Security and Login History
The last piece of identity context is where a user's credentials actually came from, and when they last logged in. Both come back empty for admin on this system - and that absence isn't a failure of the samples. It's the demonstration: a local admin account has no external identity and no login trail, which is exactly what you'd want to confirm rather than assume.
xdmp:external-security
Resolve an external security configuration name (LDAP, Kerberos, SAML) to its numeric ID — the reverse of xdmp:user-external-security below.
Source docs: https://docs.marklogic.com/11.0/xdmp:external-security
| Option / Argument | What it controls | Used here |
|---|---|---|
$external-security | External security configuration name to resolve to an ID | cleverllamas-ldap |
xquery version "1.0-ml";
try {
let $name := "cleverllamas-ldap"
return
(
"external-security-name", $name,
"external-security-id", xdmp:external-security($name)
)
} catch ($e) {
(
"external-security-name", "cleverllamas-ldap",
"error", $e/error:code/fn:string()
)
}
'use strict';
// Resolve an external security configuration name to its ID.
const name = 'cleverllamas-ldap';
let result;
try {
result = Sequence.from([
'external-security-name', name,
'external-security-id', xdmp.externalSecurity(name)
]);
} catch (e) {
// MarkLogic's error code surfaces on e.name in the JavaScript catch object, not e.code.
result = Sequence.from([
'external-security-name', name,
'error', e.name
]);
}
result;
external-security-name
cleverllamas-ldap
error
SEC-EXTSECDNE
| Line | Value |
|---|---|
| 1 | external-security-name |
| 2 | cleverllamas-ldap |
| 3 | error |
| 4 | SEC-EXTSECDNE |
What to notice: unlike the ID-resolution functions elsewhere in this article, xdmp:external-security throws (SEC-EXTSECDNE — "external security does not exist") rather than returning an empty sequence when the name does not resolve. This environment has no external security configured at all, which is the normal state for a local or development deployment — wrap the call in a try/catch when the configuration is optional, exactly as both samples here do.
xdmp:user-external-security
Check whether a user ID belongs to an externally authenticated user, and if so, which external security configuration and external user name it maps to.
Source docs: https://docs.marklogic.com/11.0/xdmp:user-external-security
| Option / Argument | What it controls | Used here |
|---|---|---|
$user-id | User ID to check for an external-security identity | ID resolved by xdmp:user(...) for the current user |
xquery version "1.0-ml";
let $user-name := xdmp:get-current-user()
let $user-id := xdmp:user($user-name)
return
(
"user-name", $user-name,
"user-id", $user-id,
"external-user-record", xdmp:user-external-security($user-id)
)
'use strict';
// Check whether a user is an externally authenticated user (LDAP, Kerberos, SAML).
// An empty result serialises as a plain JS object ({}), not null, so check its keys.
const userName = xdmp.getCurrentUser();
const userId = xdmp.user(userName);
const externalUser = xdmp.userExternalSecurity(userId);
Sequence.from([
'user-name', userName,
'user-id', userId,
'is-external-user', Object.keys(externalUser).length > 0
]);
user-name
admin
user-id
7071164303237443533
is-external-user
false
| Line | Value |
|---|---|
| 1 | user-name |
| 2 | admin |
| 3 | user-id |
| 4 | 7071164303237443533 |
| 5 | is-external-user |
| 6 | false |
What to notice: admin is an internally-authenticated user, so the result is empty — this is exactly how to tell internal and external users apart in a script. In JavaScript, an empty element(external-user)? result serialises as a plain object ({}), not null or an empty array, so check Object.keys(result).length rather than testing for falsiness directly.
xdmp:user-last-login
The last-login history recorded for the current execution user — and only the current user. There is no username parameter; this function cannot report on anyone else's login history.
Source docs: https://docs.marklogic.com/11.0/xdmp:user-last-login
| Option / Argument | What it controls | Used here |
|---|---|---|
| None | Reports the last-login record for the current execution user; the empty sequence is returned when the App Server has no last-login database configured | Read directly from current execution context |
xquery version "1.0-ml";
let $last-login := xdmp:user-last-login()
return
(
"user-name", xdmp:get-current-user(),
"last-login-tracked", fn:exists($last-login)
)
'use strict';
// Last-login history is only populated when the App Server has a last-login database configured.
// An empty result serialises as a plain JS object ({}), not null, so check its keys.
const lastLogin = xdmp.userLastLogin();
Sequence.from([
'user-name', xdmp.getCurrentUser(),
'last-login-tracked', Object.keys(lastLogin).length > 0
]);
user-name
admin
last-login-tracked
false
| Line | Value |
|---|---|
| 1 | user-name |
| 2 | admin |
| 3 | last-login-tracked |
| 4 | false |
What to notice: two things are easy to miss here. First, this function only ever reports on the current user — there is no way to pass a username and audit someone else's login history with it, unlike every other xdmp:user-* function in this article. Second, the result is empty on this system because no last-login database is configured on the App Server; where one is configured, the result is a last-login element carrying last-successful-login, last-unsuccessful-login, and number-unsuccessful-logins.
Server and Host Context
Same resolution pattern as before, new subject: instead of a user or role, it's the App Server and host that answered your request doing the identifying.
xdmp:server
The ID of the App Server handling the current request.
Source docs: https://docs.marklogic.com/11.0/xdmp:server
| Option / Argument | What it controls | Used here |
|---|---|---|
$name (optional) | App Server name to resolve to an ID | Not supplied — reports the current App Server |
$group (optional) | Group ID to scope the $name lookup, since server names are unique only within a group, not cluster-wide | Not supplied — resolved against the current group |
xquery version "1.0-ml";
xdmp:server()
'use strict';
// Get the ID of the App Server handling the current request.
xdmp.server();
17229314393548288462
| Value |
|---|
| 17229314393548288462 |
What to notice: this is the ID xdmp:server-name resolves in the next section — confirming which App Server answered matters in any environment running more than one. Pass $name to resolve a different App Server by name, and add $group when that name is not unique cluster-wide — server names only have to be unique within their own group.
xdmp:server-name
Great for logs, distributed troubleshooting, and proving which app server answered.
Source docs: https://docs.marklogic.com/11.0/xdmp:server-name
| Option / Argument | What it controls | Used here |
|---|---|---|
$id | App Server, XDBC Server, ODBC Server, or Task Server ID to resolve to a name | ID from xdmp:server() |
xquery version "1.0-ml";
(
"server-id",
xdmp:server(),
"server-name",
xdmp:server-name(xdmp:server())
)
'use strict';
// Get the current App Server ID and name.
const serverId = xdmp.server();
const serverName = xdmp.serverName(serverId);
Sequence.from([
'server-id', serverId,
'server-name', serverName
]);
server-id
17229314393548288462
server-name
App-Services
| Line | Value |
|---|---|
| 1 | server-id |
| 2 | 17229314393548288462 |
| 3 | server-name |
| 4 | App-Services |
What to notice: this is what actually settles a cross-node argument - "it works on my server" stops being an opinion once you've resolved the ID to a name. The $id argument accepts any App Server, XDBC Server, ODBC Server, or Task Server ID, not only App Server IDs, despite what the function's name implies.
xdmp:host
The ID of the host executing the current request.
Source docs: https://docs.marklogic.com/11.0/xdmp:host
| Option / Argument | What it controls | Used here |
|---|---|---|
$name (optional) | Host name to resolve to an ID | Not supplied — reports the current host |
xquery version "1.0-ml";
xdmp:host()
'use strict';
// Get the ID of the host currently executing this request.
xdmp.host();
12796697149423442590
| Value |
|---|
| 12796697149423442590 |
What to notice: in a single-node deployment there is only one host ID to see, but in a cluster this is what tells you which node actually processed the request. Pass $name to resolve a different host in the cluster by name instead of reporting the current one.
xdmp:host-name
The reverse lookup — turn a host ID back into a hostname for logs and dashboards.
Source docs: https://docs.marklogic.com/11.0/xdmp:host-name
| Option / Argument | What it controls | Used here |
|---|---|---|
$id | Host ID to resolve back to a hostname | ID from xdmp:host() |
xquery version "1.0-ml";
let $host-id := xdmp:host()
return
(
"host-id", $host-id,
"host-name", xdmp:host-name($host-id)
)
'use strict';
// Resolve a host ID back to its host name.
const hostId = xdmp.host();
const hostName = xdmp.hostName(hostId);
Sequence.from([
'host-id', hostId,
'host-name', hostName
]);
host-id
12796697149423442590
host-name
636e573c28be.lan
| Line | Value |
|---|---|
| 1 | host-id |
| 2 | 12796697149423442590 |
| 3 | host-name |
| 4 | 636e573c28be.lan |
What to notice: pairing xdmp:host with xdmp:host-name is the same pattern as the server and role/user lookups above — resolve to an ID to assert identity, resolve back to a name for anything a human needs to read.
Context is Security
Decision rule: confirm user, roles, and privileges first, then check default collections and permissions, external security, and server/host identity — resolving names to IDs (and back) wherever a script needs to assert rather than assume. Most "query bugs" under pressure are context mismatches, and most "why can they do that" questions are privilege or default-security mismatches. Work through them in that order and most of your "impossible" bugs stop being impossible before lunch.
Know who you are, then verify what you can see:
- Document Inspection Starter Pack — Inspect permissions on the documents you've just verified your access to.
- Database and Environment Starter Pack — Confirm the database and server context alongside your user and role identity.
- Runtime and Storage Starter Pack — Estimate volumes and check forest placement within the context you've just authenticated.
Need Some Help?
Looking for more information on this subject or any other topic related to MarkLogic? Contact Us (info@cleverllamas.com) to find out how we can assist you with consulting or training!
- API Context for This Pack
- Current Execution Identity
- xdmp:get-current-user
- xdmp:get-current-roles
- Name and ID Resolution
- xdmp:user
- xdmp:user-roles
- xdmp:role
- xdmp:role-name
- Privileges
- xdmp:has-privilege
- xdmp:user-privileges
- xdmp:role-privileges
- xdmp:default-collections
- xdmp:user-get-default-collections
- xdmp:role-get-default-collections
- External Security and Login History
- xdmp:external-security
- xdmp:user-external-security
- xdmp:user-last-login
- Server and Host Context
- xdmp:server
- xdmp:server-name
- xdmp:host
- xdmp:host-name
- Context is Security