Runtime and Storage Starter Pack
Fast checks for volume, placement, and document format in llamaverse
"How much content is there, where does it live, and what shape is it in?" Three questions, and most MarkLogic operators end up guessing at the answers instead of checking them - usually because the checking functions are scattered across the API reference rather than gathered somewhere useful.
This pack gathers them. Estimated counts from xdmp:estimate, forest and database placement from xdmp:node-database and friends, document format from URI and content inspection, and the binary storage model - including the split between regular and registered (external) binaries that catches people out the first time they hit it. Each example runs against real llamaverse content, so the numbers you get back are numbers you can check against a document you can actually look at.
Scope Note
There is a fourth question this pack deliberately leaves out: who has access to any of it. Permissions, collections, and role-based access are covered in depth in the Document Inspection Starter Pack - reach for that pack when the operational question turns from "what is here" to "who can see it".
The examples in this article assume the llamaverse (v2.6.0+) is deployed. The llamaverse sample data is freely available from github.com/cleverllamas/llamaverse - see the llamaverse article for full setup instructions. The binary storage examples specifically need Aaron's llama photo registered as an external binary - see "What Changed in 2.6.0" in the llamaverse article for the one-time setup step.
API Context for This Pack
| Context Item | What this pack uses |
|---|---|
| Data set | llamaverse v2.6.0+ sample data |
| Primary document scope | wild llama URIs for estimate/placement checks; llama profile photos for binary storage checks |
| Primary focus | runtime/storage facts (estimated count, forest/database placement, URI format, binary storage model) |
| Views used | None |
| Index context | Mixed: xdmp:estimate can use query/index evaluation; other calls inspect storage/runtime metadata |
If runtime numbers seem wrong, confirm you are querying the expected content database and not a different environment clone.
Functions in This Pack
xdmp:estimate
The polite way to ask, "roughly how big is this llama pile?"
Source docs: https://docs.marklogic.com/11.0/xdmp:estimate
| Option / Argument | What it controls | Used here |
|---|---|---|
$expression | Expression whose item count is estimated | URI sequence from llamaverse scope |
{
"name": "Aaron",
"breed": "Huacaya",
"placeOfBirth": "Cusco, Peru",
"secretPowerId": "d8839ba6-2b77-4bcc-9927-b86cdfecb9fb"
}
xquery version "1.0-ml";
xdmp:estimate(collection("wild-llamas"))
'use strict';
// Estimate the number of fragments in the wild-llamas collection.
// xdmp:estimate()'s JS equivalent is cts.estimate() - xdmp.estimate is not exposed to JavaScript.
const estimate = cts.estimate(cts.collectionQuery('wild-llamas'));
const results = {
collectionEstimate: estimate,
collectionName: 'wild-llamas',
message: `Estimated size of wild-llamas collection: ${estimate} fragments`
};
({
sample: 'xdmp/runtime-storage-starter-pack/assets/xdmp-estimate.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
});
4561
| Metric | Value |
|---|---|
| Result | 4561 |
What to notice: xdmp:estimate() is fast because it never opens a single document — it reads the universal index and stops there. That speed is the entire reason to reach for it over an exact count.
xdmp:document-forest
When you need to know where a document actually lives, not where you hope it lives.
Source docs: https://docs.marklogic.com/11.0/xdmp:document-forest
| Option / Argument | What it controls | Used here |
|---|---|---|
$uri | Document URI to inspect for forest placement | A wild-llama document URI |
{
"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
(
$sample-uri,
xdmp:document-forest($sample-uri),
xdmp:forest-name(xdmp:document-forest($sample-uri))
)
'use strict';
// Find a document from wild-llamas and check its forest placement.
const sampleUri = cts.uris(null, null, cts.collectionQuery('wild-llamas')).toArray()[0];
if (!sampleUri) {
throw new Error('NO-LLAMAVERSE: No documents found in collection wild-llamas.');
}
const forestId = xdmp.documentForest(sampleUri);
const forestName = xdmp.forestName(forestId);
const results = {
documentUri: sampleUri,
forestId: forestId,
forestName: forestName,
collection: 'wild-llamas'
};
({
sample: 'xdmp/runtime-storage-starter-pack/assets/xdmp-document-forest.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
1195255089468435289
cleverllamas-content-1
| Line | Value |
|---|---|
| 1 | /cleverllamas/llamaverse/raw/wild-llamas/llamas/00048384-cb13-4557-805e-a6b4e57f7eab.json |
| 2 | 1195255089468435289 |
| 3 | cleverllamas-content-1 |
What to notice: having both the forest ID and its name on hand turns a placement question from a lookup exercise into a one-line answer — exactly what you want mid-incident, not three greps deep.
xdmp:uri-format
Tiny function, big value. It settles "xml or json?" arguments in one line.
Source docs: https://docs.marklogic.com/11.0/xdmp:uri-format
| Option / Argument | What it controls | Used here |
|---|---|---|
$uri | Document URI whose format is returned | A wild-llama document URI |
{
"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
(
$sample-uri,
xdmp:uri-format($sample-uri)
)
'use strict';
// Find a document from wild-llamas and check its format.
const sampleUri = cts.uris(null, null, cts.collectionQuery('wild-llamas')).toArray()[0];
if (!sampleUri) {
throw new Error('NO-LLAMAVERSE: No documents found in collection wild-llamas.');
}
const format = xdmp.uriFormat(sampleUri);
const results = {
documentUri: sampleUri,
format: format,
collection: 'wild-llamas',
message: `Document at ${sampleUri} is in ${format} format`
};
({
sample: 'xdmp/runtime-storage-starter-pack/assets/xdmp-uri-format.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
json
| Line | Value |
|---|---|
| 1 | /cleverllamas/llamaverse/raw/wild-llamas/llamas/00048384-cb13-4557-805e-a6b4e57f7eab.json |
| 2 | json |
What to notice: a pipeline that assumes every URI is JSON will fail quietly on the one document that isn't. This check costs nothing and catches that assumption before it costs you a debugging afternoon.
The rest of this pack goes one level deeper: which database a node actually lives in, and - for binary content - whether it lives inside the database at all or is just registered from a file on disk. For collection membership and general node-kind checks, see the Document Inspection Starter Pack; this pack sticks to physical placement.
xdmp:node-database
Forest placement tells you which physical shard a document lives on. Database placement tells you which logical container that shard belongs to. Different question, same instinct: don't assume, check.
Source docs: https://docs.marklogic.com/11.0/xdmp:node-database
| Option / Argument | What it controls | Used here |
|---|---|---|
$node | Node whose owning database is returned | Katrina's profile photo binary node |
xquery version "1.0-ml";
let $photo-uri := "/cleverllamas/llamaverse/content/llamas/images/1024fa02-cd67-44f2-8d8c-0c5f16ccb7d1.gif"
let $photo := doc($photo-uri)/binary()
return
if (empty($photo)) then
error(xs:QName("NO-LLAMAVERSE"), "Katrina's profile photo was not found. Deploy llamaverse 2.6.0 or later.")
else
(
$photo-uri,
xdmp:node-database($photo),
xdmp:database-name(xdmp:node-database($photo))
)
'use strict';
// Which database is Katrina's profile photo actually stored in?
const photoUri = '/cleverllamas/llamaverse/content/llamas/images/1024fa02-cd67-44f2-8d8c-0c5f16ccb7d1.gif';
const photo = fn.head(cts.doc(photoUri));
if (!photo) {
throw new Error('NO-LLAMAVERSE: Katrina\'s profile photo was not found. Deploy llamaverse 2.6.0 or later.');
}
const databaseId = xdmp.nodeDatabase(photo);
const results = {
photoUri: photoUri,
databaseId: databaseId,
databaseName: xdmp.databaseName(databaseId)
};
({
sample: 'xdmp/runtime-storage-starter-pack/assets/xdmp-node-database.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/content/llamas/images/1024fa02-cd67-44f2-8d8c-0c5f16ccb7d1.gif
2736149102113944426
cleverllamas-content
| Line | Value |
|---|---|
| 1 | /cleverllamas/llamaverse/content/llamas/images/1024fa02-cd67-44f2-8d8c-0c5f16ccb7d1.gif |
| 2 | 2736149102113944426 |
| 3 | cleverllamas-content |
What to notice: xdmp:node-database() works on any node, not just documents - useful when you already have a node in hand and don't want to re-resolve its URI first. Pair it with xdmp:document-forest() above when you need both the database and the forest.
xdmp:binary-is-external
Same content type, two different storage stories. Katrina's photo lives inside the database like any other binary; Aaron's lives on the filesystem, and the database document just holds a pointer to it.
Source docs: https://docs.marklogic.com/11.0/xdmp:binary-is-external
| Option / Argument | What it controls | Used here |
|---|---|---|
$source | Binary node to test | Katrina's regular photo and Aaron's registered photo |
xquery version "1.0-ml";
let $katrina-uri := "/cleverllamas/llamaverse/content/llamas/images/1024fa02-cd67-44f2-8d8c-0c5f16ccb7d1.gif"
let $aaron-uri := "/cleverllamas/llamaverse/content/llamas/images/0c8bdb0d-ac62-49b7-ac74-94dbba46efa5.gif"
let $katrina := doc($katrina-uri)/binary()
let $aaron := doc($aaron-uri)/binary()
return
if (empty($katrina) or empty($aaron)) then
error(xs:QName("NO-LLAMAVERSE"), "Katrina's or Aaron's profile photo was not found. Deploy llamaverse 2.6.0 or later and register Aaron's external binary.")
else
(
"Katrina: " || xdmp:binary-is-external($katrina),
"Aaron: " || xdmp:binary-is-external($aaron)
)
'use strict';
// Same content type, two different storage models: compare Katrina (regular) and Aaron (registered/external).
function binaryNode(uri) {
const doc = fn.head(cts.doc(uri));
return doc ? fn.head(doc.xpath('node()')) : null;
}
const katrinaUri = '/cleverllamas/llamaverse/content/llamas/images/1024fa02-cd67-44f2-8d8c-0c5f16ccb7d1.gif';
const aaronUri = '/cleverllamas/llamaverse/content/llamas/images/0c8bdb0d-ac62-49b7-ac74-94dbba46efa5.gif';
const katrina = binaryNode(katrinaUri);
const aaron = binaryNode(aaronUri);
if (!katrina || !aaron) {
throw new Error('NO-LLAMAVERSE: Katrina\'s or Aaron\'s profile photo was not found. Deploy llamaverse 2.6.0 or later and register Aaron\'s external binary.');
}
const results = {
katrina: { uri: katrinaUri, isExternal: xdmp.binaryIsExternal(katrina) },
aaron: { uri: aaronUri, isExternal: xdmp.binaryIsExternal(aaron) }
};
({
sample: 'xdmp/runtime-storage-starter-pack/assets/xdmp-binary-is-external.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
});
Katrina: false
Aaron: true
| Llama | Binary type | xdmp:binary-is-external() |
|---|---|---|
| Katrina | Regular (in-database) | false |
| Aaron | Registered (external) | true |
What to notice: this is the function that actually distinguishes the two storage models. Everything else in this section - size, database, forest - looks the same for both; only xdmp:binary-is-external() tells you the bytes aren't where you'd assume.
xdmp:binary-size
Source docs: https://docs.marklogic.com/11.0/xdmp:binary-size
| Option / Argument | What it controls | Used here |
|---|---|---|
$source | Binary node whose byte length is returned | Katrina's and Aaron's photos |
xquery version "1.0-ml";
let $katrina-uri := "/cleverllamas/llamaverse/content/llamas/images/1024fa02-cd67-44f2-8d8c-0c5f16ccb7d1.gif"
let $aaron-uri := "/cleverllamas/llamaverse/content/llamas/images/0c8bdb0d-ac62-49b7-ac74-94dbba46efa5.gif"
let $katrina := doc($katrina-uri)/binary()
let $aaron := doc($aaron-uri)/binary()
return
if (empty($katrina) or empty($aaron)) then
error(xs:QName("NO-LLAMAVERSE"), "Katrina's or Aaron's profile photo was not found. Deploy llamaverse 2.6.0 or later and register Aaron's external binary.")
else
(
"Katrina: " || xdmp:binary-size($katrina),
"Aaron: " || xdmp:binary-size($aaron)
)
'use strict';
// Binary size in bytes is the same kind of number regardless of storage model.
function binaryNode(uri) {
const doc = fn.head(cts.doc(uri));
return doc ? fn.head(doc.xpath('node()')) : null;
}
const katrinaUri = '/cleverllamas/llamaverse/content/llamas/images/1024fa02-cd67-44f2-8d8c-0c5f16ccb7d1.gif';
const aaronUri = '/cleverllamas/llamaverse/content/llamas/images/0c8bdb0d-ac62-49b7-ac74-94dbba46efa5.gif';
const katrina = binaryNode(katrinaUri);
const aaron = binaryNode(aaronUri);
if (!katrina || !aaron) {
throw new Error('NO-LLAMAVERSE: Katrina\'s or Aaron\'s profile photo was not found. Deploy llamaverse 2.6.0 or later and register Aaron\'s external binary.');
}
const results = {
katrina: { uri: katrinaUri, sizeBytes: xdmp.binarySize(katrina) },
aaron: { uri: aaronUri, sizeBytes: xdmp.binarySize(aaron) }
};
({
sample: 'xdmp/runtime-storage-starter-pack/assets/xdmp-binary-size.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
});
Katrina: 331994
Aaron: 488467
| Llama | Size (bytes) |
|---|---|
| Katrina | 331994 |
| Aaron | 488467 |
What to notice: xdmp:binary-size() returns the same kind of number regardless of storage model - it doesn't care whether the bytes sit in the database or on disk.
xdmp:binary-is-large and xdmp:binary-is-small
These two answer "does this binary get special large-object treatment?" The cleverllamas-content database's large-size-threshold is configured at 1024 KB (1 MB); both sample photos sit comfortably under that, so neither is flagged large.
Source docs: https://docs.marklogic.com/11.0/xdmp:binary-is-large and https://docs.marklogic.com/11.0/xdmp:binary-is-small
| Option / Argument | What it controls | Used here |
|---|---|---|
$source | Binary node to test | Katrina's and Aaron's photos |
xquery version "1.0-ml";
let $katrina-uri := "/cleverllamas/llamaverse/content/llamas/images/1024fa02-cd67-44f2-8d8c-0c5f16ccb7d1.gif"
let $aaron-uri := "/cleverllamas/llamaverse/content/llamas/images/0c8bdb0d-ac62-49b7-ac74-94dbba46efa5.gif"
let $katrina := doc($katrina-uri)/binary()
let $aaron := doc($aaron-uri)/binary()
return
if (empty($katrina) or empty($aaron)) then
error(xs:QName("NO-LLAMAVERSE"), "Katrina's or Aaron's profile photo was not found. Deploy llamaverse 2.6.0 or later and register Aaron's external binary.")
else
(
"Katrina: large=" || xdmp:binary-is-large($katrina) || " small=" || xdmp:binary-is-small($katrina),
"Aaron: large=" || xdmp:binary-is-large($aaron) || " small=" || xdmp:binary-is-small($aaron)
)
'use strict';
// A binary can be neither large nor small - both flags describe internal storage tiering.
function binaryNode(uri) {
const doc = fn.head(cts.doc(uri));
return doc ? fn.head(doc.xpath('node()')) : null;
}
const katrinaUri = '/cleverllamas/llamaverse/content/llamas/images/1024fa02-cd67-44f2-8d8c-0c5f16ccb7d1.gif';
const aaronUri = '/cleverllamas/llamaverse/content/llamas/images/0c8bdb0d-ac62-49b7-ac74-94dbba46efa5.gif';
const katrina = binaryNode(katrinaUri);
const aaron = binaryNode(aaronUri);
if (!katrina || !aaron) {
throw new Error('NO-LLAMAVERSE: Katrina\'s or Aaron\'s profile photo was not found. Deploy llamaverse 2.6.0 or later and register Aaron\'s external binary.');
}
const results = {
katrina: { uri: katrinaUri, sizeBytes: xdmp.binarySize(katrina), isLarge: xdmp.binaryIsLarge(katrina), isSmall: xdmp.binaryIsSmall(katrina) },
aaron: { uri: aaronUri, sizeBytes: xdmp.binarySize(aaron), isLarge: xdmp.binaryIsLarge(aaron), isSmall: xdmp.binaryIsSmall(aaron) }
};
({
sample: 'xdmp/runtime-storage-starter-pack/assets/xdmp-binary-is-large-and-small.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
});
Katrina: large=false small=true
Aaron: large=false small=false
| Llama | Size (bytes) | is-large | is-small |
|---|---|---|---|
| Katrina | 331994 | false | true |
| Aaron | 488467 | false | false |
What to notice: "small" and "large" aren't opposites here - a binary can be neither, sitting in the middle range. Both flags describe internal storage tiering, not whether the content feels big to a human.
xdmp:external-binary-path
Source docs: https://docs.marklogic.com/11.0/xdmp:external-binary-path
| Option / Argument | What it controls | Used here |
|---|---|---|
$source | Binary node to inspect | Aaron's registered photo, and Katrina's regular one for contrast |
xquery version "1.0-ml";
let $katrina-uri := "/cleverllamas/llamaverse/content/llamas/images/1024fa02-cd67-44f2-8d8c-0c5f16ccb7d1.gif"
let $aaron-uri := "/cleverllamas/llamaverse/content/llamas/images/0c8bdb0d-ac62-49b7-ac74-94dbba46efa5.gif"
let $katrina := doc($katrina-uri)/binary()
let $aaron := doc($aaron-uri)/binary()
return
if (empty($katrina) or empty($aaron)) then
error(xs:QName("NO-LLAMAVERSE"), "Katrina's or Aaron's profile photo was not found. Deploy llamaverse 2.6.0 or later and register Aaron's external binary.")
else
(
"Aaron: " || (xdmp:external-binary-path($aaron), "(no path returned)")[1],
"Katrina: " || (xdmp:external-binary-path($katrina), "(empty sequence - not a registered binary)")[1]
)
'use strict';
// xdmp.externalBinaryPath() quietly returns an empty sequence for a regular binary instead of raising an error.
function binaryNode(uri) {
const doc = fn.head(cts.doc(uri));
return doc ? fn.head(doc.xpath('node()')) : null;
}
const katrinaUri = '/cleverllamas/llamaverse/content/llamas/images/1024fa02-cd67-44f2-8d8c-0c5f16ccb7d1.gif';
const aaronUri = '/cleverllamas/llamaverse/content/llamas/images/0c8bdb0d-ac62-49b7-ac74-94dbba46efa5.gif';
const katrina = binaryNode(katrinaUri);
const aaron = binaryNode(aaronUri);
if (!katrina || !aaron) {
throw new Error('NO-LLAMAVERSE: Katrina\'s or Aaron\'s profile photo was not found. Deploy llamaverse 2.6.0 or later and register Aaron\'s external binary.');
}
const aaronPath = fn.head(xdmp.externalBinaryPath(aaron));
const katrinaPath = fn.head(xdmp.externalBinaryPath(katrina));
const results = {
aaron: { uri: aaronUri, externalBinaryPath: aaronPath !== null ? aaronPath : '(no path returned)' },
katrina: { uri: katrinaUri, externalBinaryPath: katrinaPath !== null ? katrinaPath : '(empty sequence - not a registered binary)' }
};
({
sample: 'xdmp/runtime-storage-starter-pack/assets/xdmp-external-binary-path.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
});
Aaron: /var/opt/MarkLogic/external-binaries/llamas/0c8bdb0d-ac62-49b7-ac74-94dbba46efa5.gif
Katrina: (empty sequence - not a registered binary)
| Llama | xdmp:external-binary-path() |
|---|---|
| Aaron | /var/opt/MarkLogic/external-binaries/llamas/0c8bdb0d-ac62-49b7-ac74-94dbba46efa5.gif |
| Katrina | empty sequence |
What to notice: the function quietly returns an empty sequence for a regular binary instead of raising an error - check xdmp:binary-is-external() first if you need to tell "not registered" apart from "registered but the path is unavailable."
xdmp:filesystem-file-exists
The natural next question once you have a path: is the file actually still there? Registering an external binary only stores a path - MarkLogic doesn't guarantee the file hasn't been moved, renamed, or deleted underneath it.
Source docs: https://docs.marklogic.com/11.0/xdmp:filesystem-file-exists
| Option / Argument | What it controls | Used here |
|---|---|---|
$pathname | Filesystem path to check | Aaron's registered photo path, plus a deliberately made-up path |
$host | Host to check on (defaults to the current host) | Not supplied - uses the current host |
xquery version "1.0-ml";
let $aaron-uri := "/cleverllamas/llamaverse/content/llamas/images/0c8bdb0d-ac62-49b7-ac74-94dbba46efa5.gif"
let $aaron := doc($aaron-uri)/binary()
return
if (empty($aaron)) then
error(xs:QName("NO-LLAMAVERSE"), "Aaron's profile photo was not found. Deploy llamaverse 2.6.0 or later and register Aaron's external binary.")
else
let $real-path := xdmp:external-binary-path($aaron)
let $made-up-path := "/var/opt/MarkLogic/external-binaries/llamas/does-not-exist.gif"
return
(
"Real path exists: " || xdmp:filesystem-file-exists($real-path),
"Made-up path exists: " || xdmp:filesystem-file-exists($made-up-path)
)
'use strict';
// The check happens on the MarkLogic host's filesystem, not the client's.
function binaryNode(uri) {
const doc = fn.head(cts.doc(uri));
return doc ? fn.head(doc.xpath('node()')) : null;
}
const aaronUri = '/cleverllamas/llamaverse/content/llamas/images/0c8bdb0d-ac62-49b7-ac74-94dbba46efa5.gif';
const aaron = binaryNode(aaronUri);
if (!aaron) {
throw new Error('NO-LLAMAVERSE: Aaron\'s profile photo was not found. Deploy llamaverse 2.6.0 or later and register Aaron\'s external binary.');
}
const realPath = xdmp.externalBinaryPath(aaron);
const madeUpPath = '/var/opt/MarkLogic/external-binaries/llamas/does-not-exist.gif';
const results = {
realPath: { path: realPath, exists: xdmp.filesystemFileExists(realPath) },
madeUpPath: { path: madeUpPath, exists: xdmp.filesystemFileExists(madeUpPath) }
};
({
sample: 'xdmp/runtime-storage-starter-pack/assets/xdmp-filesystem-file-exists.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
});
Real path exists: true
Made-up path exists: false
| Path | Exists |
|---|---|
| Aaron's real external-binary path | true |
| A deliberately made-up path | false |
What to notice: this check runs against the MarkLogic host's filesystem, not the client's - useful for catching a registered binary whose backing file quietly went missing during a migration or host move.
Operational Wisdom Awaits
Decision rule: measure placement and format before tuning performance assumptions; wrong storage assumptions compound quickly.
Now that you understand volume and placement, take these insights deeper:
- Database and Environment Starter Pack — Verify you're measuring the right database and understand its role in your deployment.
- Document Inspection Starter Pack — Inspect individual documents to spot format anomalies that
xdmp:uri-format()can confirm. - Identity and Context Starter Pack — Understand who's asking these questions and from which server they're running.
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
- Functions in This Pack
- xdmp:estimate
- xdmp:document-forest
- xdmp:uri-format
- xdmp:node-database
- xdmp:binary-is-external
- xdmp:binary-size
- xdmp:binary-is-large and xdmp:binary-is-small
- xdmp:external-binary-path
- xdmp:filesystem-file-exists
- Operational Wisdom Awaits