URI and Collection Auditing Starter Pack

Reliable URI-level checks for real llamaverse operations

personClever Llamas
CleverLlamasMinimum Llamaverse Version: 2
databaseMinimum MarkLogic Version: 11

Identifiers, collection filters, and outputs stay visible together so the audit trail is obvious at a glance.

This pack is for URI-level reality checks, because indexes are honest even when dashboards are not.

When production numbers disagree, start here before debating application code.

The examples keep the result tab down to identifiers and collection evidence so the audit trail is obvious at a glance.

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 ItemWhat this pack uses
Data setllamaverse v2.0+ sample data
Primary document scopewild llama JSON documents (/cleverllamas/llamaverse/raw/wild-llamas/llamas/{uuid}.json)
Primary constraintsURI enumeration and collection filters/matches
Fields usedNone in these examples
Index contextURI and collection lookups resolved directly through cts index structures

If URI counts differ from expectation, start by validating collection names and wildcard patterns before changing query composition.

Functions in This Pack

cts:uris

If you need a quick list of what matched, this is your sharpest knife.

Source docs: https://docs.marklogic.com/11.0/cts:uris

Option / ArgumentWhat it controlsUsed here
$startThe first URI (or index position) to returnNot set in this sample (default start position applies)
$optionsOrdering and URI-source behaviour"document"
$queryCTS query that limits which URIs are returnedCollection-scoped query
$options ValueWhat it controlsDefault when omitted
"document" / "properties" / "locks"Which fragment class contributes URI values"document"
"item-order"Returns results in fragment order instead of pure lexical orderNot enabled
"ascending" / "descending"URI sort direction for lexical output"ascending"
{
  "name": "Aaron",
  "breed": "Huacaya",
  "placeOfBirth": "Cusco, Peru",
  "secretPowerId": "d8839ba6-2b77-4bcc-9927-b86cdfecb9fb"
}
xquery version "1.0-ml";

cts:uris((), (), cts:collection-query("wild-llamas"))[1 to 25]
'use strict';

const query = cts.collectionQuery('llamaverse');
const results = cts.uris(null, ['limit=10'], query).toArray();

({
  sample: 'cts/uri-and-collection-auditing-starter-pack/assets/cts-uris.sjs',
  kind: Array.isArray(results) ? (results.every((item) => typeof item === 'object' && 'subject' in item && 'predicate' in item && 'object' in item) ? 'triples' : 'rows') : ((results !== null && typeof results === 'object') ? 'object' : 'scalar'),
  count: Array.isArray(results) ? results.length : 0,
  data: results
});
/cleverllamas/llamaverse/raw/wild-llamas/llamas/00048384-cb13-4557-805e-a6b4e57f7eab.json
/cleverllamas/llamaverse/raw/wild-llamas/llamas/0005e261-4302-4ae8-9574-732a54040423.json
/cleverllamas/llamaverse/raw/wild-llamas/llamas/000eca10-d166-469f-b17a-3c3b35ee0883.json
/cleverllamas/llamaverse/raw/wild-llamas/llamas/002c7133-e985-4bd6-9ea8-f057fa0c6ee7.json
/cleverllamas/llamaverse/raw/wild-llamas/llamas/0043e95e-3209-4b97-8871-f9b7073377f2.json
/cleverllamas/llamaverse/raw/wild-llamas/llamas/006c5ffa-6c5e-4169-8a08-eec49f48148c.json
/cleverllamas/llamaverse/raw/wild-llamas/llamas/007229e2-ee25-47c1-b18a-2e0c0ec0dbcd.json
/cleverllamas/llamaverse/raw/wild-llamas/llamas/00863414-306e-49cb-acd0-6579bea5421e.json
/cleverllamas/llamaverse/raw/wild-llamas/llamas/0087ad24-a720-4d82-b513-79ae5feebcc6.json
/cleverllamas/llamaverse/raw/wild-llamas/llamas/009cf2b9-d4db-4491-9cc2-34e2f43a5ee1.json
/cleverllamas/llamaverse/raw/wild-llamas/llamas/00a0fe3a-da61-493c-990e-af7719db0d18.json
/cleverllamas/llamaverse/raw/wild-llamas/llamas/00cf82a3-4937-40c6-80fe-6ae0f1100364.json
... (13 more URIs)
#URI
1/cleverllamas/llamaverse/raw/wild-llamas/llamas/00048384-cb13-4557-805e-a6b4e57f7eab.json
2/cleverllamas/llamaverse/raw/wild-llamas/llamas/0005e261-4302-4ae8-9574-732a54040423.json
3/cleverllamas/llamaverse/raw/wild-llamas/llamas/000eca10-d166-469f-b17a-3c3b35ee0883.json
4/cleverllamas/llamaverse/raw/wild-llamas/llamas/002c7133-e985-4bd6-9ea8-f057fa0c6ee7.json
5/cleverllamas/llamaverse/raw/wild-llamas/llamas/0043e95e-3209-4b97-8871-f9b7073377f2.json
6/cleverllamas/llamaverse/raw/wild-llamas/llamas/006c5ffa-6c5e-4169-8a08-eec49f48148c.json
7/cleverllamas/llamaverse/raw/wild-llamas/llamas/007229e2-ee25-47c1-b18a-2e0c0ec0dbcd.json
8/cleverllamas/llamaverse/raw/wild-llamas/llamas/00863414-306e-49cb-acd0-6579bea5421e.json
9/cleverllamas/llamaverse/raw/wild-llamas/llamas/0087ad24-a720-4d82-b513-79ae5feebcc6.json
10/cleverllamas/llamaverse/raw/wild-llamas/llamas/009cf2b9-d4db-4491-9cc2-34e2f43a5ee1.json

What to notice: cts:uris is the fastest way to inspect match sets when you only need identifiers.

cts:collection-query

The cleanest way to say, "show me only the documents from this data lane."

Source docs: https://docs.marklogic.com/11.0/cts:collection-query

Option / ArgumentWhat it controlsUsed here
$urisCollection URI or URIs to matchSingle llamaverse collection URI
$optionHow multiple URIs are evaluated ("any" or "exact")Default behaviour ("any") in sample
{
  "name": "Aaron",
  "breed": "Huacaya",
  "placeOfBirth": "Cusco, Peru",
  "secretPowerId": "d8839ba6-2b77-4bcc-9927-b86cdfecb9fb"
}
xquery version "1.0-ml";

let $sample-uri := cts:uris((), (), cts:collection-query("wild-llamas"))[1]
return
  if (empty($sample-uri)) then
    error(xs:QName("NO-LLAMAVERSE"), "No documents found in collection 'wild-llamas'.")
  else
    cts:search(fn:doc(), cts:collection-query("wild-llamas"))[1 to 10] ! xdmp:node-uri(.)
'use strict';

const query = cts.collectionQuery('llamaverse');
const results = cts.search(fn.doc(), query).toArray().slice(0, 10).map((doc) => ({
  uri: xdmp.nodeUri(doc)
}));

({
  sample: 'cts/uri-and-collection-auditing-starter-pack/assets/cts-collection-query.sjs',
  kind: Array.isArray(results) ? (results.every((item) => typeof item === 'object' && 'subject' in item && 'predicate' in item && 'object' in item) ? 'triples' : 'rows') : ((results !== null && typeof results === 'object') ? 'object' : 'scalar'),
  count: Array.isArray(results) ? results.length : 0,
  data: results
});
/cleverllamas/llamaverse/raw/wild-llamas/llamas/4429e229-490a-4398-992e-84d0f4737d6d.json
/cleverllamas/llamaverse/raw/wild-llamas/llamas/67384a21-62fe-4f80-a964-72783cfb076f.json
/cleverllamas/llamaverse/raw/wild-llamas/llamas/b3591799-54a8-44ea-87a1-d1c05659f781.json
/cleverllamas/llamaverse/raw/wild-llamas/llamas/c45a4f65-d14a-4206-b921-ffc9470e14bb.json
/cleverllamas/llamaverse/raw/wild-llamas/movement/2022_W12_batch6.json
/cleverllamas/llamaverse/raw/wild-llamas/movement/2022_W15_batch4.json
/cleverllamas/llamaverse/raw/wild-llamas/movement/2022_W18_batch2.json
/cleverllamas/llamaverse/raw/wild-llamas/movement/2023_W41_batch1.json
/cleverllamas/llamaverse/raw/wild-llamas/movement/2024_W24_batch5.json
/cleverllamas/llamaverse/raw/wild-llamas/movement/2024_W27_batch3.json
#URI
1/cleverllamas/llamaverse/raw/wild-llamas/llamas/4429e229-490a-4398-992e-84d0f4737d6d.json
2/cleverllamas/llamaverse/raw/wild-llamas/llamas/67384a21-62fe-4f80-a964-72783cfb076f.json
3/cleverllamas/llamaverse/raw/wild-llamas/llamas/b3591799-54a8-44ea-87a1-d1c05659f781.json
4/cleverllamas/llamaverse/raw/wild-llamas/llamas/c45a4f65-d14a-4206-b921-ffc9470e14bb.json
5/cleverllamas/llamaverse/raw/wild-llamas/movement/2022_W12_batch6.json
6/cleverllamas/llamaverse/raw/wild-llamas/movement/2022_W15_batch4.json
7/cleverllamas/llamaverse/raw/wild-llamas/movement/2022_W18_batch2.json
8/cleverllamas/llamaverse/raw/wild-llamas/movement/2023_W41_batch1.json
9/cleverllamas/llamaverse/raw/wild-llamas/movement/2024_W24_batch5.json
10/cleverllamas/llamaverse/raw/wild-llamas/movement/2024_W27_batch3.json

What to notice: the sample proves collection constraints remain explicit and easy to audit.

cts:collection-match

Great for collection discovery when someone forgot to write that wiki page.

Source docs: https://docs.marklogic.com/11.0/cts:collection-match

Option / ArgumentWhat it controlsUsed here
$patternWildcard expression used to discover collection URIsPattern targeting llamaverse collection names
$limitMaximum number of collection names returnedNot set in this sample
{
  "name": "Aaron",
  "breed": "Huacaya",
  "placeOfBirth": "Cusco, Peru",
  "secretPowerId": "d8839ba6-2b77-4bcc-9927-b86cdfecb9fb"
}
xquery version "1.0-ml";

cts:collection-match("wild-*")
'use strict';

const results = cts.collectionMatch('llamaverse*').toArray();

({
  sample: 'cts/uri-and-collection-auditing-starter-pack/assets/cts-collection-match.sjs',
  kind: Array.isArray(results) ? (results.every((item) => typeof item === 'object' && 'subject' in item && 'predicate' in item && 'object' in item) ? 'triples' : 'rows') : ((results !== null && typeof results === 'object') ? 'object' : 'scalar'),
  count: Array.isArray(results) ? results.length : 0,
  data: results
});
wild-llamas
LineValue
1wild-llamas

What to notice: wildcard collection discovery is handy for environment reconnaissance and naming validation.

Auditing is Just the Beginning

Decision rule: when counts look wrong, validate URIs and collections first, then debug higher-level query composition.

Now that you understand URIs and collections at the index level, explore how they combine with other operations:

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!