Relevance and Scoring Starter Pack
Understand what ranked first and why
Each example keeps the score values, the query, and the output together — so when someone asks why this result ranked first, you have the receipts.
When somebody asks "why did this result rank first?", this pack gives you receipts.
The examples call out the score-related values that explain ranking and keep the results tabs trimmed to the fields that matter for that explanation.
The examples in this article assume the llamaverse (v2.4.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.4.0+ sample data |
| Quality profile | Curated document quality values on selected wild llama profiles, providing non-zero cts:quality() output in read-only relevance diagnostics |
| Primary document scope | wild llama JSON documents (/cleverllamas/llamaverse/raw/wild-llamas/llamas/{uuid}.json) |
| Query entry point | cts:search-style result nodes used to inspect score attributes |
| Fields used | None in these examples |
| Index context | Relevance and score metadata are resolved in the cts search/index layer |
If score behaviour looks surprising, verify that the query options are the ones you intend and that you are comparing nodes returned from the same query context.
Relevance Signals at a Glance
Functions in This Pack
cts:score
The relevance number everyone argues about and nobody should ignore.
Source docs: https://docs.marklogic.com/11.0/cts:score
| Option / Argument | What it controls | Used here |
|---|---|---|
$node | The result node from which score metadata is read | A node returned by cts:search(...) |
$logtf | Logarithmic tf scaling mode for score calculation | Not set in this sample |
{
"name": "Aaron",
"breed": "Huacaya",
"placeOfBirth": "Cusco, Peru",
"secretPowerId": "d8839ba6-2b77-4bcc-9927-b86cdfecb9fb"
}
xquery version "1.0-ml";
let $query := cts:and-query((
cts:collection-query("wild-llamas"),
cts:word-query("sung")
))
for $node in cts:search(fn:doc(), $query)[1 to 5]
return
map:entry("uri", xdmp:node-uri($node))
=> map:with("score", cts:score($node))
'use strict';
const query = cts.andQuery([
cts.collectionQuery('wild-llamas'),
cts.wordQuery('sung')
]);
const results = cts.search(query).toArray().slice(0, 5).map((doc) => ({
uri: xdmp.nodeUri(doc),
score: cts.score(doc)
}));
({
sample: 'cts/relevance-and-scoring-starter-pack/assets/cts-score.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
});
[
{
"score": 16896,
"uri": "/cleverllamas/llamaverse/raw/wild-llamas/llamas/c45a4f65-d14a-4206-b921-ffc9470e14bb.json"
},
{
"score": 16896,
"uri": "/cleverllamas/llamaverse/raw/wild-llamas/llamas/4429e229-490a-4398-992e-84d0f4737d6d.json"
},
{
"score": 16896,
"uri": "/cleverllamas/llamaverse/raw/wild-llamas/llamas/d9af3805-d87d-473b-b01f-67bc8628e3df.json"
},
{
"score": 16896,
"uri": "/cleverllamas/llamaverse/raw/wild-llamas/llamas/78a3ea33-382d-486a-aece-77bae497af14.json"
},
{
"score": 16896,
"uri": "/cleverllamas/llamaverse/raw/wild-llamas/llamas/3cb1a513-b57b-49c4-b80a-e67aa99dd272.json"
},
{
"score": 16896,
"uri": "/cleverllamas/llamaverse/raw/wild-llamas/llamas/7ceb979a-b831-48fd-8b1a-a1c724370ba1.json"
},
{
"score": 16896,
"uri": "/cleverllamas/llamaverse/raw/wild-llamas/llamas/b67c3b62-b38b-4cb8-ae04-88a2fdd1ebda.json"
},
{
"score": 16896,
"uri": "/cleverllamas/llamaverse/raw/wild-llamas/llamas/24a25bb9-b35f-48b3-b01c-d8f4a64d7a2d.json"
},
{
"score": 16896,
"uri": "/cleverllamas/llamaverse/raw/wild-llamas/llamas/eaa6c416-ef46-4f91-b861-1e99b28ae18b.json"
},
{
"score": 16896,
"uri": "/cleverllamas/llamaverse/raw/wild-llamas/llamas/58fc1645-17d2-4732-aded-1e88f637f967.json"
}
]
| Score | URI |
|---|---|
| 16896 | /cleverllamas/llamaverse/raw/wild-llamas/llamas/c45a4f65-d14a-4206-b921-ffc9470e14bb.json |
| 16896 | /cleverllamas/llamaverse/raw/wild-llamas/llamas/4429e229-490a-4398-992e-84d0f4737d6d.json |
| 16896 | /cleverllamas/llamaverse/raw/wild-llamas/llamas/d9af3805-d87d-473b-b01f-67bc8628e3df.json |
| 16896 | /cleverllamas/llamaverse/raw/wild-llamas/llamas/78a3ea33-382d-486a-aece-77bae497af14.json |
| 16896 | /cleverllamas/llamaverse/raw/wild-llamas/llamas/3cb1a513-b57b-49c4-b80a-e67aa99dd272.json |
| 16896 | /cleverllamas/llamaverse/raw/wild-llamas/llamas/7ceb979a-b831-48fd-8b1a-a1c724370ba1.json |
| 16896 | /cleverllamas/llamaverse/raw/wild-llamas/llamas/b67c3b62-b38b-4cb8-ae04-88a2fdd1ebda.json |
| 16896 | /cleverllamas/llamaverse/raw/wild-llamas/llamas/24a25bb9-b35f-48b3-b01c-d8f4a64d7a2d.json |
| 16896 | /cleverllamas/llamaverse/raw/wild-llamas/llamas/eaa6c416-ef46-4f91-b861-1e99b28ae18b.json |
| 16896 | /cleverllamas/llamaverse/raw/wild-llamas/llamas/58fc1645-17d2-4732-aded-1e88f637f967.json |
What to notice: this sample currently returns equal score values for the shown rows, which is still useful for demonstrating how to inspect score metadata directly.
cts:confidence
Useful when raw score numbers are technically correct but conversationally useless.
Source docs: https://docs.marklogic.com/11.0/cts:confidence
| Option / Argument | What it controls | Used here |
|---|---|---|
$node | The result node from which confidence is read | A node returned by cts:search(...) |
{
"name": "Aaron",
"breed": "Huacaya",
"placeOfBirth": "Cusco, Peru",
"secretPowerId": "d8839ba6-2b77-4bcc-9927-b86cdfecb9fb"
}
xquery version "1.0-ml";
let $query := cts:and-query((
cts:collection-query("wild-llamas"),
cts:word-query("sung")
))
for $node in cts:search(fn:doc(), $query)[1 to 5]
return
map:entry("uri", xdmp:node-uri($node))
=> map:with("score", cts:score($node))
=> map:with("confidence", cts:confidence($node))
'use strict';
const query = cts.andQuery([
cts.collectionQuery('wild-llamas'),
cts.wordQuery('sung')
]);
const results = cts.search(query).toArray().slice(0, 5).map((doc) => ({
uri: xdmp.nodeUri(doc),
score: cts.score(doc),
confidence: cts.confidence(doc)
}));
({
sample: 'cts/relevance-and-scoring-starter-pack/assets/cts-confidence.sjs',
kind: Array.isArray(results) ? 'rows' : 'object',
count: Array.isArray(results) ? results.length : 0,
data: results
});
[
{
"score": 58368,
"uri": "/cleverllamas/llamaverse/raw/wild-llamas/llamas/0a6911e5-0d17-44e1-a114-cb747490f469.json",
"confidence": 0.4191779
},
{
"score": 28416,
"uri": "/cleverllamas/llamaverse/raw/wild-llamas/llamas/507cf4de-4469-497f-9888-7756c592b119.json",
"confidence": 0.2889328
},
{
"score": 27648,
"uri": "/cleverllamas/llamaverse/raw/wild-llamas/llamas/19be9dcc-fd35-4c54-b503-63a6a8a1043d.json",
"confidence": 0.2889328
},
{
"score": 27392,
"uri": "/cleverllamas/llamaverse/raw/wild-llamas/llamas/24a25bb9-b35f-48b3-b01c-d8f4a64d7a2d.json",
"confidence": 0.2889328
},
{
"score": 27136,
"uri": "/cleverllamas/llamaverse/raw/wild-llamas/llamas/cd37f616-e707-47f3-99c0-d20def77c1a6.json",
"confidence": 0.2889328
}
]
| Score | Confidence | URI |
|---|---|---|
| 58368 | 0.4191779 | /cleverllamas/llamaverse/raw/wild-llamas/llamas/0a6911e5-0d17-44e1-a114-cb747490f469.json |
| 28416 | 0.2889328 | /cleverllamas/llamaverse/raw/wild-llamas/llamas/507cf4de-4469-497f-9888-7756c592b119.json |
| 27648 | 0.2889328 | /cleverllamas/llamaverse/raw/wild-llamas/llamas/19be9dcc-fd35-4c54-b503-63a6a8a1043d.json |
| 27392 | 0.2889328 | /cleverllamas/llamaverse/raw/wild-llamas/llamas/24a25bb9-b35f-48b3-b01c-d8f4a64d7a2d.json |
| 27136 | 0.2889328 | /cleverllamas/llamaverse/raw/wild-llamas/llamas/cd37f616-e707-47f3-99c0-d20def77c1a6.json |
What to notice: confidence gives you a normalised scoring signal that is easier to compare across nearby results than a large integer score on its own.
cts:fitness
Useful when you want another relevance signal in the room before somebody starts "fixing" the ranking by gut feel.
Source docs: https://docs.marklogic.com/11.0/cts:fitness
| Option / Argument | What it controls | Used here |
|---|---|---|
$node | The result node from which fitness is read | A node returned by cts:search(...) |
{
"name": "Aaron",
"breed": "Huacaya",
"placeOfBirth": "Cusco, Peru",
"secretPowerId": "d8839ba6-2b77-4bcc-9927-b86cdfecb9fb"
}
xquery version "1.0-ml";
let $query := cts:and-query((
cts:collection-query("wild-llamas"),
cts:word-query("sung")
))
for $node in cts:search(fn:doc(), $query)[1 to 5]
return
map:entry("uri", xdmp:node-uri($node))
=> map:with("score", cts:score($node))
=> map:with("fitness", cts:fitness($node))
'use strict';
const query = cts.andQuery([
cts.collectionQuery('wild-llamas'),
cts.wordQuery('sung')
]);
const results = cts.search(query).toArray().slice(0, 5).map((doc) => ({
uri: xdmp.nodeUri(doc),
score: cts.score(doc),
fitness: cts.fitness(doc)
}));
({
sample: 'cts/relevance-and-scoring-starter-pack/assets/cts-fitness.sjs',
kind: Array.isArray(results) ? 'rows' : 'object',
count: Array.isArray(results) ? results.length : 0,
data: results
});
[
{
"score": 58368,
"fitness": 0.3951162,
"uri": "/cleverllamas/llamaverse/raw/wild-llamas/llamas/0a6911e5-0d17-44e1-a114-cb747490f469.json"
},
{
"score": 28416,
"fitness": 0.2723475,
"uri": "/cleverllamas/llamaverse/raw/wild-llamas/llamas/507cf4de-4469-497f-9888-7756c592b119.json"
},
{
"score": 27648,
"fitness": 0.2723475,
"uri": "/cleverllamas/llamaverse/raw/wild-llamas/llamas/19be9dcc-fd35-4c54-b503-63a6a8a1043d.json"
},
{
"score": 27392,
"fitness": 0.2723475,
"uri": "/cleverllamas/llamaverse/raw/wild-llamas/llamas/24a25bb9-b35f-48b3-b01c-d8f4a64d7a2d.json"
},
{
"score": 27136,
"fitness": 0.2723475,
"uri": "/cleverllamas/llamaverse/raw/wild-llamas/llamas/cd37f616-e707-47f3-99c0-d20def77c1a6.json"
}
]
| Score | Fitness | URI |
|---|---|---|
| 58368 | 0.3951162 | /cleverllamas/llamaverse/raw/wild-llamas/llamas/0a6911e5-0d17-44e1-a114-cb747490f469.json |
| 28416 | 0.2723475 | /cleverllamas/llamaverse/raw/wild-llamas/llamas/507cf4de-4469-497f-9888-7756c592b119.json |
| 27648 | 0.2723475 | /cleverllamas/llamaverse/raw/wild-llamas/llamas/19be9dcc-fd35-4c54-b503-63a6a8a1043d.json |
| 27392 | 0.2723475 | /cleverllamas/llamaverse/raw/wild-llamas/llamas/24a25bb9-b35f-48b3-b01c-d8f4a64d7a2d.json |
| 27136 | 0.2723475 | /cleverllamas/llamaverse/raw/wild-llamas/llamas/cd37f616-e707-47f3-99c0-d20def77c1a6.json |
What to notice: fitness gives a second normalised relevance lens. It often tracks confidence closely, but treating them as identical is how ranking conversations get fuzzy.
cts:remainder
Useful for quick UI pagination estimates when exact counts are overkill.
Source docs: https://docs.marklogic.com/11.0/cts:remainder
| Option / Argument | What it controls | Used here |
|---|---|---|
$node | The result node whose remaining-count estimate is requested | A node returned by cts:search(...) |
{
"name": "Aaron",
"breed": "Huacaya",
"placeOfBirth": "Cusco, Peru",
"secretPowerId": "d8839ba6-2b77-4bcc-9927-b86cdfecb9fb"
}
xquery version "1.0-ml";
let $query := cts:and-query((
cts:collection-query("wild-llamas"),
cts:word-query("sung")
))
for $node in cts:search(fn:doc(), $query)[1 to 5]
return
map:entry("uri", xdmp:node-uri($node))
=> map:with("remainder", cts:remainder($node))
'use strict';
const query = cts.andQuery([
cts.collectionQuery('wild-llamas'),
cts.wordQuery('sung')
]);
const results = cts.search(query).toArray().slice(0, 5).map((doc) => ({
uri: xdmp.nodeUri(doc),
remainder: cts.remainder(doc)
}));
({
sample: 'cts/relevance-and-scoring-starter-pack/assets/cts-remainder.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
});
[
{
"uri": "/cleverllamas/llamaverse/raw/wild-llamas/llamas/c45a4f65-d14a-4206-b921-ffc9470e14bb.json",
"remainder": 3001
},
{
"uri": "/cleverllamas/llamaverse/raw/wild-llamas/llamas/4429e229-490a-4398-992e-84d0f4737d6d.json",
"remainder": 3000
},
{
"uri": "/cleverllamas/llamaverse/raw/wild-llamas/llamas/d9af3805-d87d-473b-b01f-67bc8628e3df.json",
"remainder": 2999
},
{
"uri": "/cleverllamas/llamaverse/raw/wild-llamas/llamas/78a3ea33-382d-486a-aece-77bae497af14.json",
"remainder": 2998
},
{
"uri": "/cleverllamas/llamaverse/raw/wild-llamas/llamas/3cb1a513-b57b-49c4-b80a-e67aa99dd272.json",
"remainder": 2997
}
]
| URI | Remainder |
|---|---|
/cleverllamas/llamaverse/raw/wild-llamas/llamas/c45a4f65-d14a-4206-b921-ffc9470e14bb.json | 3001 |
/cleverllamas/llamaverse/raw/wild-llamas/llamas/4429e229-490a-4398-992e-84d0f4737d6d.json | 3000 |
/cleverllamas/llamaverse/raw/wild-llamas/llamas/d9af3805-d87d-473b-b01f-67bc8628e3df.json | 2999 |
/cleverllamas/llamaverse/raw/wild-llamas/llamas/78a3ea33-382d-486a-aece-77bae497af14.json | 2998 |
/cleverllamas/llamaverse/raw/wild-llamas/llamas/3cb1a513-b57b-49c4-b80a-e67aa99dd272.json | 2997 |
What to notice: remainder approximates remaining result volume from each returned node context.
cts:quality
A reminder that ranking is not only text relevance.
Source docs: https://docs.marklogic.com/11.0/cts:quality
| Option / Argument | What it controls | Used here |
|---|---|---|
$node | The result node from which quality is read | A node returned by cts:search(...) |
This example is read-only and uses the llamaverse v2.4.0+ quality-profile URI set. Selected wild llama profiles carry curated non-zero document quality values so quality contribution is visible without mutation during runtime.
{
"name": "Aaron",
"breed": "Huacaya",
"placeOfBirth": "Cusco, Peru",
"secretPowerId": "d8839ba6-2b77-4bcc-9927-b86cdfecb9fb"
}
xquery version "1.0-ml";
let $profile-uris := (
"/cleverllamas/llamaverse/raw/wild-llamas/llamas/0a6911e5-0d17-44e1-a114-cb747490f469.json",
"/cleverllamas/llamaverse/raw/wild-llamas/llamas/8520c251-7abe-4eb4-a0e8-6706bf5c2397.json",
"/cleverllamas/llamaverse/raw/wild-llamas/llamas/24a25bb9-b35f-48b3-b01c-d8f4a64d7a2d.json",
"/cleverllamas/llamaverse/raw/wild-llamas/llamas/58fc1645-17d2-4732-aded-1e88f637f967.json",
"/cleverllamas/llamaverse/raw/wild-llamas/llamas/e3f48f8f-ea2b-4382-8313-02430bf34a45.json",
"/cleverllamas/llamaverse/raw/wild-llamas/llamas/507cf4de-4469-497f-9888-7756c592b119.json",
"/cleverllamas/llamaverse/raw/wild-llamas/llamas/19be9dcc-fd35-4c54-b503-63a6a8a1043d.json",
"/cleverllamas/llamaverse/raw/wild-llamas/llamas/cd37f616-e707-47f3-99c0-d20def77c1a6.json",
"/cleverllamas/llamaverse/raw/wild-llamas/llamas/d50a73a0-c096-4f79-99a0-8bd05a426416.json",
"/cleverllamas/llamaverse/raw/wild-llamas/llamas/74a7c489-3515-45f9-88bd-2e8261a7e720.json"
)
for $node in fn:doc($profile-uris)
order by cts:quality($node) descending, xdmp:node-uri($node)
return
map:entry("uri", xdmp:node-uri($node))
=> map:with("quality", cts:quality($node))
'use strict';
const profileUris = [
'/cleverllamas/llamaverse/raw/wild-llamas/llamas/0a6911e5-0d17-44e1-a114-cb747490f469.json',
'/cleverllamas/llamaverse/raw/wild-llamas/llamas/8520c251-7abe-4eb4-a0e8-6706bf5c2397.json',
'/cleverllamas/llamaverse/raw/wild-llamas/llamas/24a25bb9-b35f-48b3-b01c-d8f4a64d7a2d.json',
'/cleverllamas/llamaverse/raw/wild-llamas/llamas/58fc1645-17d2-4732-aded-1e88f637f967.json',
'/cleverllamas/llamaverse/raw/wild-llamas/llamas/e3f48f8f-ea2b-4382-8313-02430bf34a45.json',
'/cleverllamas/llamaverse/raw/wild-llamas/llamas/507cf4de-4469-497f-9888-7756c592b119.json',
'/cleverllamas/llamaverse/raw/wild-llamas/llamas/19be9dcc-fd35-4c54-b503-63a6a8a1043d.json',
'/cleverllamas/llamaverse/raw/wild-llamas/llamas/cd37f616-e707-47f3-99c0-d20def77c1a6.json',
'/cleverllamas/llamaverse/raw/wild-llamas/llamas/d50a73a0-c096-4f79-99a0-8bd05a426416.json',
'/cleverllamas/llamaverse/raw/wild-llamas/llamas/74a7c489-3515-45f9-88bd-2e8261a7e720.json'
];
const results = profileUris
.map((uri) => fn.doc(uri))
.filter((doc) => doc)
.map((doc) => ({
uri: xdmp.nodeUri(doc),
quality: cts.quality(doc)
}))
.sort((a, b) => (b.quality - a.quality) || a.uri.localeCompare(b.uri));
({
sample: 'cts/relevance-and-scoring-starter-pack/assets/cts-quality.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
});
[
{
"uri": "/cleverllamas/llamaverse/raw/wild-llamas/llamas/0a6911e5-0d17-44e1-a114-cb747490f469.json",
"quality": 7
},
{
"uri": "/cleverllamas/llamaverse/raw/wild-llamas/llamas/507cf4de-4469-497f-9888-7756c592b119.json",
"quality": 6
},
{
"uri": "/cleverllamas/llamaverse/raw/wild-llamas/llamas/d50a73a0-c096-4f79-99a0-8bd05a426416.json",
"quality": 5
},
{
"uri": "/cleverllamas/llamaverse/raw/wild-llamas/llamas/8520c251-7abe-4eb4-a0e8-6706bf5c2397.json",
"quality": 4
},
{
"uri": "/cleverllamas/llamaverse/raw/wild-llamas/llamas/19be9dcc-fd35-4c54-b503-63a6a8a1043d.json",
"quality": 3
},
{
"uri": "/cleverllamas/llamaverse/raw/wild-llamas/llamas/24a25bb9-b35f-48b3-b01c-d8f4a64d7a2d.json",
"quality": 2
},
{
"uri": "/cleverllamas/llamaverse/raw/wild-llamas/llamas/74a7c489-3515-45f9-88bd-2e8261a7e720.json",
"quality": 2
},
{
"uri": "/cleverllamas/llamaverse/raw/wild-llamas/llamas/cd37f616-e707-47f3-99c0-d20def77c1a6.json",
"quality": 1
},
{
"uri": "/cleverllamas/llamaverse/raw/wild-llamas/llamas/58fc1645-17d2-4732-aded-1e88f637f967.json",
"quality": 0
},
{
"uri": "/cleverllamas/llamaverse/raw/wild-llamas/llamas/e3f48f8f-ea2b-4382-8313-02430bf34a45.json",
"quality": -1
}
]
| URI | Quality |
|---|---|
/cleverllamas/llamaverse/raw/wild-llamas/llamas/0a6911e5-0d17-44e1-a114-cb747490f469.json | 7 |
/cleverllamas/llamaverse/raw/wild-llamas/llamas/507cf4de-4469-497f-9888-7756c592b119.json | 6 |
/cleverllamas/llamaverse/raw/wild-llamas/llamas/d50a73a0-c096-4f79-99a0-8bd05a426416.json | 5 |
/cleverllamas/llamaverse/raw/wild-llamas/llamas/8520c251-7abe-4eb4-a0e8-6706bf5c2397.json | 4 |
/cleverllamas/llamaverse/raw/wild-llamas/llamas/19be9dcc-fd35-4c54-b503-63a6a8a1043d.json | 3 |
/cleverllamas/llamaverse/raw/wild-llamas/llamas/24a25bb9-b35f-48b3-b01c-d8f4a64d7a2d.json | 2 |
/cleverllamas/llamaverse/raw/wild-llamas/llamas/74a7c489-3515-45f9-88bd-2e8261a7e720.json | 2 |
/cleverllamas/llamaverse/raw/wild-llamas/llamas/cd37f616-e707-47f3-99c0-d20def77c1a6.json | 1 |
/cleverllamas/llamaverse/raw/wild-llamas/llamas/58fc1645-17d2-4732-aded-1e88f637f967.json | 0 |
/cleverllamas/llamaverse/raw/wild-llamas/llamas/e3f48f8f-ea2b-4382-8313-02430bf34a45.json | -1 |
What to notice: quality reveals non-text ranking contribution and is useful in relevance tuning sessions.
cts:relevance-info
Useful when the team stops asking for scores and starts asking for a proper explanation.
Source docs: https://docs.marklogic.com/11.0/cts:relevance-info
| Option / Argument | What it controls | Used here |
|---|---|---|
$node | The result node from which relevance trace information is read | A node returned by cts:search(...) with tracing enabled |
Tiny Flight Recorder, Not Automatic Magic
cts:relevance-info() is the tiny flight recorder for ranking. But it only records anything when you run cts:search(..., ("relevance-trace")) first. No trace flag, no recorder, no breadcrumbs, just polite silence.
{
"name": "Aaron",
"breed": "Huacaya",
"placeOfBirth": "Cusco, Peru",
"secretPowerId": "d8839ba6-2b77-4bcc-9927-b86cdfecb9fb"
}
xquery version "1.0-ml";
let $query := cts:and-query((
cts:collection-query("wild-llamas"),
cts:word-query("sung")
))
for $node in cts:search(fn:doc(), $query, ("relevance-trace"))[1 to 3]
let $info := cts:relevance-info($node)
let $trace := xdmp:quote($info)
return
map:entry("uri", xdmp:node-uri($node))
=> map:with("score", cts:score($node))
=> map:with("traceRecorded", fn:exists($info))
=> map:with("traceChars", fn:string-length($trace))
=> map:with("tracePreview", fn:substring($trace, 1, 140))
'use strict';
const query = cts.andQuery([
cts.collectionQuery('wild-llamas'),
cts.wordQuery('sung')
]);
const results = cts.search(query, ['relevance-trace']).toArray().slice(0, 3).map((doc) => {
const info = cts.relevanceInfo(doc);
const trace = xdmp.quote(info);
return {
uri: xdmp.nodeUri(doc),
score: cts.score(doc),
traceRecorded: fn.exists(info),
traceChars: fn.stringLength(trace),
tracePreview: fn.substring(trace, 1, 140)
};
});
({
sample: 'cts/relevance-and-scoring-starter-pack/assets/cts-relevance-info.sjs',
kind: Array.isArray(results) ? 'rows' : 'object',
count: Array.isArray(results) ? results.length : 0,
data: results
});
[
{
"score": 58368,
"uri": "/cleverllamas/llamaverse/raw/wild-llamas/llamas/0a6911e5-0d17-44e1-a114-cb747490f469.json",
"traceRecorded": true,
"traceChars": 1272,
"tracePreview": "<qry:relevance-info xmlns:qry=\"http://marklogic.com/cts/query\">\n <qry:score formula=\"(256*scoreSum/weightSum)+(256*qualityWeight*documentQu"
},
{
"score": 28416,
"uri": "/cleverllamas/llamaverse/raw/wild-llamas/llamas/507cf4de-4469-497f-9888-7756c592b119.json",
"traceRecorded": true,
"traceChars": 1052,
"tracePreview": "<qry:relevance-info xmlns:qry=\"http://marklogic.com/cts/query\">\n <qry:score formula=\"(256*scoreSum/weightSum)+(256*qualityWeight*documentQu"
},
{
"score": 27648,
"uri": "/cleverllamas/llamaverse/raw/wild-llamas/llamas/19be9dcc-fd35-4c54-b503-63a6a8a1043d.json",
"traceRecorded": true,
"traceChars": 1052,
"tracePreview": "<qry:relevance-info xmlns:qry=\"http://marklogic.com/cts/query\">\n <qry:score formula=\"(256*scoreSum/weightSum)+(256*qualityWeight*documentQu"
}
]
| Score | Trace Recorded | Trace Chars | URI |
|---|---|---|---|
| 58368 | true | 1272 | /cleverllamas/llamaverse/raw/wild-llamas/llamas/0a6911e5-0d17-44e1-a114-cb747490f469.json |
| 28416 | true | 1052 | /cleverllamas/llamaverse/raw/wild-llamas/llamas/507cf4de-4469-497f-9888-7756c592b119.json |
| 27648 | true | 1052 | /cleverllamas/llamaverse/raw/wild-llamas/llamas/19be9dcc-fd35-4c54-b503-63a6a8a1043d.json |
What to notice: the trace payload is intentionally previewed rather than dumped in full. For ranking analysis, confirming that trace data exists and inspecting a short excerpt is usually enough to prove that explainability is available.
Unlocking the Next Mystery
Decision rule: if ranking questions are slowing delivery, instrument score early and treat query shape as part of your relevance contract.
If you're enjoying the scoring hunt, these sibling topics will deepen your understanding of how MarkLogic ranks results:
- Search Composition Starter Pack — Master
cts:search()and query composition, the foundation that determines which documents get scored in the first place. - Text Query Building Starter Pack — Explore
cts:word-query()and boolean logic. Your query shape directly influences how scores are calculated.
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
- Relevance Signals at a Glance
- Functions in This Pack
- cts:score
- cts:confidence
- cts:fitness
- cts:remainder
- cts:quality
- cts:relevance-info