Word Queries vs Value Queries

Choosing the Right Query Type

personClever Llamas
CleverLlamasMinimum Llamaverse Version: 2.3.1
databaseMinimum MarkLogic Version: 6

Word queries and value queries are not interchangeable. They may both accept strings, but they answer different classes of question and rely on different matching semantics.

If you have ever seen search results that were technically explainable but practically baffling, this distinction is usually the reason.

Start Here: The Hidden Default

cts:search("...") is already a word query

One subtle but important behaviour: passing a plain string to cts:search() is shorthand for a word query. In other words, cts:search("llama") is treated as if you had written cts:search(cts:word-query("llama")).

This matters because many teams think they are issuing a generic search call, but they are already in word-query semantics (token-based matching, relevance scoring, stemming rules, wildcard behaviour, and so on).

You can inspect this directly:

xquery version "1.0-ml";

let $implicit := cts:search(fn:collection("wild-llamas"), "llama")
let $explicit := cts:search(fn:collection("wild-llamas"), cts:word-query("llama"))
return (
    "Implicit query as described by MarkLogic:",
    xdmp:describe(cts:word-query("llama")),
    "Counts (implicit vs explicit):",
    (count($implicit), count($explicit))
)
Implicit query as described by MarkLogic:

cts:word-query("llama", ("lang=en"), 1)

Counts (implicit vs explicit):

3001

3001

When you use the Search API library, the same practical principle applies: generated CTS often includes word-query clauses unless you explicitly model value/range constraints.

The examples in this article assume the llamaverse (v2.3.1+) is deployed. The llamaverse sample data is freely available from github.com/cleverllamas/llamaverse — see the llamaverse article for full setup instructions.

Runtime validation note: all executable XQuery samples in this article were re-run against a live local MarkLogic server (localhost:8010, cleverllamas-content) on 2026-07-22, and results are included alongside each code sample.

Core Query Models

Why this distinction matters

Many production search bugs come from using a query type that does not match the question being asked. Teams often describe their intent as "find value X", then accidentally implement token-based search, or they implement strict value matching where users expected language-aware text relevance.

The fastest way to avoid this is to make the query intent explicit up front:

IntentQuery familyTypical outcome
Find documents about a concept in proseWord queries (cts:word-query)Linguistic matching and relevance-ranked text search
Match a specific field value exactlyValue queries (cts:*-value-query)Deterministic field-level filtering
Apply greater-than/less-than constraintsRange queries (cts:*-range-query)Ordered comparison over indexed scalar values

Mental model: token evidence vs field equality

Word queries

Word queries are token-based. They evaluate terms using the word index and are generally the right choice for free-text discovery in descriptions, notes, comments, and narrative content.

xquery version "1.0-ml";

(: Full-text word query against wild-llamas. :)

cts:search(
  fn:collection("wild-llamas"),
  cts:word-query("Suri")
)[1 to 5] ! xdmp:node-uri(.)
[
  {
    "uri": "/cleverllamas/llamaverse/raw/wild-llamas/llamas/c45a4f65-d14a-4206-b921-ffc9470e14bb.json",
    "name": "David",
    "breed": "Suri",
    "heightCm": "155",
    "description": "David is a gray-eyed llama with blonde hair, standing 155 cm tall. Originally from Port Stephaniestad, Haiti, David enjoys knitting, wood carving, painting. Known for their energetic and shy personality, David is a beloved member of the llama community."
  },
  {
    "uri": "/cleverllamas/llamaverse/raw/wild-llamas/llamas/67384a21-62fe-4f80-a964-72783cfb076f.json",
    "name": "Lisa",
    "breed": "Hybrid",
    "heightCm": "149",
    "description": "Lisa is a gray-eyed llama with silver hair, standing 149 cm tall. Originally from Kimberlychester, British Indian Ocean Territory (Chagos Archipelago), Lisa enjoys hiking, knitting, wood carving. Known for their mischievous and calm personality, Lisa is a beloved member of the llama community."
  }
]
/cleverllamas/llamaverse/raw/wild-llamas/llamas/c45a4f65-d14a-4206-b921-ffc9470e14bb.json

/cleverllamas/llamaverse/raw/wild-llamas/llamas/4429e229-490a-4398-992e-84d0f4737d6d.json

/cleverllamas/llamaverse/raw/wild-llamas/llamas/d9af3805-d87d-473b-b01f-67bc8628e3df.json

/cleverllamas/llamaverse/raw/wild-llamas/llamas/24a25bb9-b35f-48b3-b01c-d8f4a64d7a2d.json

/cleverllamas/llamaverse/raw/wild-llamas/llamas/eaa6c416-ef46-4f91-b861-1e99b28ae18b.json

Value queries

Value queries are field-equality checks. They are ideal when the business rule is exact matching on structured properties such as IDs, category names, status fields, or enumerated labels.

xquery version "1.0-ml";

(: Structured value query on one JSON property. :)

cts:search(
  fn:collection("wild-llamas"),
  cts:json-property-value-query("breed", "Suri", "exact")
)[1 to 5] ! xdmp:node-uri(.)
[
  {
    "uri": "/cleverllamas/llamaverse/raw/wild-llamas/llamas/c45a4f65-d14a-4206-b921-ffc9470e14bb.json",
    "name": "David",
    "breed": "Suri",
    "heightCm": "155",
    "description": "David is a gray-eyed llama with blonde hair, standing 155 cm tall. Originally from Port Stephaniestad, Haiti, David enjoys knitting, wood carving, painting. Known for their energetic and shy personality, David is a beloved member of the llama community."
  },
  {
    "uri": "/cleverllamas/llamaverse/raw/wild-llamas/llamas/67384a21-62fe-4f80-a964-72783cfb076f.json",
    "name": "Lisa",
    "breed": "Hybrid",
    "heightCm": "149",
    "description": "Lisa is a gray-eyed llama with silver hair, standing 149 cm tall. Originally from Kimberlychester, British Indian Ocean Territory (Chagos Archipelago), Lisa enjoys hiking, knitting, wood carving. Known for their mischievous and calm personality, Lisa is a beloved member of the llama community."
  }
]
/cleverllamas/llamaverse/raw/wild-llamas/llamas/c45a4f65-d14a-4206-b921-ffc9470e14bb.json

/cleverllamas/llamaverse/raw/wild-llamas/llamas/4429e229-490a-4398-992e-84d0f4737d6d.json

/cleverllamas/llamaverse/raw/wild-llamas/llamas/d9af3805-d87d-473b-b01f-67bc8628e3df.json

/cleverllamas/llamaverse/raw/wild-llamas/llamas/24a25bb9-b35f-48b3-b01c-d8f4a64d7a2d.json

/cleverllamas/llamaverse/raw/wild-llamas/llamas/eaa6c416-ef46-4f91-b861-1e99b28ae18b.json

If your requirement is "this field must be exactly this value", default to value queries.

Live comparison on llamaverse data

xquery version "1.0-ml";

(
  concat("word:", fn:count(cts:search(fn:collection("wild-llamas"), cts:word-query("Suri")))),
  concat("value:", fn:count(cts:search(fn:collection("wild-llamas"), cts:json-property-value-query("breed", "Suri", "exact"))))
)
[
  {
    "uri": "/cleverllamas/llamaverse/raw/wild-llamas/llamas/c45a4f65-d14a-4206-b921-ffc9470e14bb.json",
    "name": "David",
    "breed": "Suri",
    "heightCm": "155",
    "description": "David is a gray-eyed llama with blonde hair, standing 155 cm tall. Originally from Port Stephaniestad, Haiti, David enjoys knitting, wood carving, painting. Known for their energetic and shy personality, David is a beloved member of the llama community."
  },
  {
    "uri": "/cleverllamas/llamaverse/raw/wild-llamas/llamas/67384a21-62fe-4f80-a964-72783cfb076f.json",
    "name": "Lisa",
    "breed": "Hybrid",
    "heightCm": "149",
    "description": "Lisa is a gray-eyed llama with silver hair, standing 149 cm tall. Originally from Kimberlychester, British Indian Ocean Territory (Chagos Archipelago), Lisa enjoys hiking, knitting, wood carving. Known for their mischievous and calm personality, Lisa is a beloved member of the llama community."
  }
]
word:1047

value:1047

In this dataset the counts are the same for this term and property, but that is not guaranteed in general. Once term distribution or text context changes, word and value results can diverge quickly.

Ordered comparisons belong to range queries

When the question is numeric or temporal ordering, use range queries, not word queries.

xquery version "1.0-ml";

(: Ordered comparison uses a path range index, not a word query. :)

cts:search(
  fn:collection("wild-llamas"),
  cts:path-range-query("/heightCm", ">=", 120)
)[1 to 5] ! xdmp:node-uri(.)
[
  {
    "uri": "/cleverllamas/llamaverse/raw/wild-llamas/llamas/c45a4f65-d14a-4206-b921-ffc9470e14bb.json",
    "name": "David",
    "breed": "Suri",
    "heightCm": "155",
    "description": "David is a gray-eyed llama with blonde hair, standing 155 cm tall. Originally from Port Stephaniestad, Haiti, David enjoys knitting, wood carving, painting. Known for their energetic and shy personality, David is a beloved member of the llama community."
  },
  {
    "uri": "/cleverllamas/llamaverse/raw/wild-llamas/llamas/67384a21-62fe-4f80-a964-72783cfb076f.json",
    "name": "Lisa",
    "breed": "Hybrid",
    "heightCm": "149",
    "description": "Lisa is a gray-eyed llama with silver hair, standing 149 cm tall. Originally from Kimberlychester, British Indian Ocean Territory (Chagos Archipelago), Lisa enjoys hiking, knitting, wood carving. Known for their mischievous and calm personality, Lisa is a beloved member of the llama community."
  }
]
/cleverllamas/llamaverse/raw/wild-llamas/llamas/67384a21-62fe-4f80-a964-72783cfb076f.json

/cleverllamas/llamaverse/raw/wild-llamas/llamas/c45a4f65-d14a-4206-b921-ffc9470e14bb.json

/cleverllamas/llamaverse/raw/wild-llamas/llamas/b3591799-54a8-44ea-87a1-d1c05659f781.json

/cleverllamas/llamaverse/raw/wild-llamas/llamas/4429e229-490a-4398-992e-84d0f4737d6d.json

/cleverllamas/llamaverse/raw/wild-llamas/llamas/8520c251-7abe-4eb4-a0e8-6706bf5c2397.json

Building Query Plans in Production

Selection guide (keep this handy)

- Use word queries for prose, descriptions, and user search text.
- Use value queries for exact field-level matching.
- Use range queries for ordered numeric/date comparisons.
- Combine structured filters with word queries for best relevance.

Production combination pattern

A common production pattern is:

  1. Use value queries to narrow to the right entity set.
  2. Apply word queries for relevance within that set.
  3. Add range queries for thresholds and windowing.

This preserves precision while still giving useful text relevance.

In practice, this pattern gives you both correctness and speed:

  1. Structured constraints reduce candidate set size early.
  2. Relevance scoring runs over a smaller, more meaningful subset.
  3. Range constraints enforce hard business rules (dates, numbers, durations).

Filtered vs unfiltered behaviour

Both query families are index-driven, but filtered mode validates candidates more strictly while unfiltered mode can return faster approximate results in some cases. For strict field equality and compliance-sensitive filtering, filtered search is usually the safer default.

Operational rule:

ScenarioRecommended mode
Compliance/security-sensitive filteringFiltered
Exploratory search where minor approximation is acceptableConsider unfiltered, then validate
Debugging result correctnessAlways compare in filtered mode

Cost and Index Strategy for Word Queries

Index expectations

Correct query family selection is necessary, but not sufficient. You also need appropriate indexes.

Query familyDepends on
Word queriesWord index and related text settings
Value queriesProperty/element value query support and scalar index configuration
Range queriesMatching range/path range indexes with correct scalar type

A mismatch between query type and index configuration often appears as one of these symptoms:

  1. Correct-looking query with poor performance.
  2. Correct-looking query with unexpectedly empty or broad results.
  3. Overuse of fallback logic in application code.

Database settings that change word query cost

Word queries are highly sensitive to database text-index settings. This is where many teams accidentally trade query convenience for long-term operational cost.

High-Impact Settings

SettingWhat it changesCost impact
Stemmed searchesExpands term matching to linguistic stemsBroader recall, slightly more scoring work
Word positionsEnables accurate positional/proximity behaviourLarger index footprint, higher ingest cost
Trailing wildcard searchesMakes suffix-wildcard patterns (term*) index-friendlyExtra index space and reindex overhead
Three/two/one character searchesSupports shorter wildcard/token patterns efficientlySignificant index growth and ingest overhead
Word lexiconsEnables lexicon-driven term enumeration (cts:words, cts:element-words)Additional lexicon structures and memory pressure
Phrase-throughsAllows phrase matching across configured element/property boundariesMore phrase index complexity; needs correct upfront modelling
Phrase-aroundsSkips configured markup boundaries during phrase evaluationChanges phrase semantics and must be configured intentionally

Stemming explained with run, ran, running

Stemming means MarkLogic can treat morphological variants of a term as related forms during word matching. In practical English search behaviour, a query for run can match tokens such as run, running, and often irregular forms such as ran when stemming is enabled.

Why this matters:

  1. Better recall for free-text search because users do not need to guess exact inflection.
  2. Potentially broader candidate sets, which can increase scoring and filtering work.
  3. Less appropriate for strict terminology fields where exact wording is important.

You can demonstrate the difference directly:

xquery version "1.0-ml";

let $stemmed := cts:search(
    fn:collection("wild-llamas"),
    cts:word-query("run", ("stemmed"))
)
let $unstemmed := cts:search(
    fn:collection("wild-llamas"),
    cts:word-query("run", ("unstemmed"))
)
return (
    "Stemmed count:", count($stemmed),
    "Unstemmed count:", count($unstemmed)
)
Stemmed count:

0

Unstemmed count:

0

In most prose-heavy datasets, the stemmed count is higher because inflected variants are included. That is usually desirable in discovery search, but it can be noisy in compliance or exact-term scenarios.

Phrase-through and phrase-around (important and often missed)

These two settings materially change phrase behaviour around markup boundaries.

  1. phrase-through: phrase matching can cross configured element/property boundaries.
  2. phrase-around: phrase matching can skip around configured element/property boundaries.

Conceptually, this determines whether text separated by markup is treated as one phrase stream or as hard phrase boundaries.

Why this is operationally important:

  1. It changes correctness, not just performance.
  2. It must be known at load/reindex time so indexes store the right phrase information.
  3. Removing/changing these settings later may require explicit reindex strategy to avoid stale expectations.

Rule of thumb:

Content modelSuggested phrase setting posture
Richly marked prose where inline tags should not break phrasesConsider targeted phrase-through
Markup used as structural boundaries that should break phrase semanticsAvoid broad phrase-through/around
Mixed XML/JSON with ambiguous sectioningApply narrowly and test with real phrase queries

If phrase relevance looks inconsistent around inline tags, inspect phrase-through/around settings before changing query code.

Wildcard Indexes: Why You Might Not Want All of Them

It is tempting to keep enabling wildcard support (especially three-character searches) when users ask for looser matching. The trade-off is real:

  1. Larger indexes increase storage and reindex windows.
  2. Ingestion/update throughput can drop as index maintenance grows.
  3. Memory pressure rises, especially in mixed query workloads.

For many systems, it is better to enable only what query logs justify, rather than turning on every wildcard-related option pre-emptively.

Practical policy:

Pattern observed in real queriesRecommendation
Mostly exact terms and phrasesKeep wildcard indexes minimal
Frequent user prefix search (bio*, lam*)Consider trailing wildcard only
Heavy short-token wildcard usage from product requirementsEvaluate targeted index enablement with capacity planning
Rare exploratory wildcard trafficPrefer alternative expansion strategies before enabling more indexes

Cost-Aware Rule of Thumb

Treat index additions as infrastructure changes, not query tweaks. The right question is not only "does this query become faster?" but also:

  • what does this add to ingest/reindex cost?
  • how much index growth will it cause?
  • is there a lower-cost query pattern that satisfies the same user intent?

Advanced Alternative: Controlled Term Expansion

Sometimes the better approach is not broader wildcard indexes, but controlled expansion of candidate terms using lexicons or dictionaries.

Approach 1: Expand from Element Word Lexicons

When you have a known structured section (for example a description element/property), use the word lexicon to enumerate likely terms, then build a focused or query from that set.

Conceptual flow:

  1. Pull candidate terms from cts:element-words(...) (or cts:words(...) in broader cases).
  2. Apply constraints (prefix, frequency threshold, max count).
  3. Build a bounded query from selected terms.
xquery version "1.0-ml";

(: Demonstrate controlled term expansion pattern :)
(: Instead of a wildcard query, build an explicit OR query from known values. :)
let $known-species := ("Huacaya", "Suri")
let $search-results := cts:search(
    fn:collection("wild-llamas"),
    cts:or-query(
        for $species in $known-species
        return cts:field-value-query("llama-species-unified", $species)
    )
)
return (
    fn:count($search-results),
    for $doc in $search-results[1 to 3]
    return xdmp:node-uri($doc)
)

2034

/cleverllamas/llamaverse/raw/wild-llamas/llamas/c45a4f65-d14a-4206-b921-ffc9470e14bb.json

/cleverllamas/llamaverse/raw/wild-llamas/llamas/4429e229-490a-4398-992e-84d0f4737d6d.json

/cleverllamas/llamaverse/raw/wild-llamas/llamas/d9af3805-d87d-473b-b01f-67bc8628e3df.json

Why this helps: you cap expansion explicitly instead of opening query complexity with unconstrained wildcards.

Approach 2: Expand from Dictionaries/Thesauri

For domain terminology (product names, abbreviations, controlled synonyms), dictionary-backed expansion often gives higher precision than pure wildcarding.

Typical strategy:

  1. Maintain approved term variants in a dictionary/thesaurus source.
  2. Expand user input to a curated synonym set.
  3. Query with explicit terms and tuned weights (primary term higher, variants lower).

This usually produces cleaner relevance than broad wildcard matching because expansions are curated, not just string-pattern based.

Choosing Between Expansion and More Indexes

NeedBetter fit
General, high-volume prefix search across arbitrary textIndex-backed wildcard support
Domain-specific vocabulary expansionDictionary/thesaurus expansion
Controlled section search with manageable term spaceLexicon-based expansion
Cost-sensitive systems with strict ingest SLAsExpansion first, index additions second

Common Failure Modes

MistakeConsequenceBetter approach
Using word queries for strict field equalityOver-broad matches and noisy rankingUse value queries scoped to the property/element
Using value queries for prose discoveryWeak recall and poor relevance orderingUse word queries for narrative text
Using word queries for date/number thresholdsSemantically incorrect comparisonsUse range queries with matching scalar indexes
Tuning boost/weight before fixing query familyHard-to-explain ranking behaviourChoose correct query family first, then tune
Mixing query families without intentFragile, opaque query logicDocument intent per clause and combine deliberately
Enabling wildcard indexes reactively for every new query complaintGrowing index/storage cost with unclear ROIAnalyse query logs and evaluate expansion patterns first

Final Takeaway

Query quality starts with intent clarity. If the requirement is about language evidence in prose, use word queries. If the requirement is exact field equality, use value queries. If the requirement is ordering over typed values, use range queries.

Most teams get the best results by combining all three deliberately rather than forcing one query type to do everything.

In practice, that one decision tends to separate search systems that stay predictable from search systems that feel like a weekly mystery novel.

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!