Exploring op.fromLexicons()

Turn indexed lexicon values into join-friendly row plans

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

op.fromLexicons() sources rows directly from range, URI, and collection lexicons. That makes it a strong fit when you need indexed values in a row shape ready for projection, filtering, or joining in a larger plan.

If you need a refresher on lexicon fundamentals, see Understanding Lexicons. The key difference: use this when you want fragment-linked lexicon rows rather than just a distinct value list.

Llamaverse Context for This API Call

Context ItemWhat this article uses
Data setllamaverse v2.0+ sample data
Primary source documentswild llama JSON documents
Lexicon references shownJSON property and path range references (for example breed and root-level identifiers)
Views usedNone (this call reads lexicons directly)
Field usageNone in these examples
Index contextrequired range/path indexes must exist before op.fromLexicons() can return rows

If the plan returns no rows, validate index definitions first. op.fromLexicons() cannot infer values for indexes that are missing or misconfigured.

Source Docs and Configuration Used

ItemValue used in this article
MarkLogic API docsop:from-lexicons, op.fromLexicons, cts:values
Llamaverse source collectionwild-llamas
Llamaverse source URI pattern/cleverllamas/llamaverse/raw/wild-llamas/llamas/{uuid}.json
Required database configPath range index on /heightCm (type=int) and range reference for breed used in the examples

Parameters

NameDatatypeRequiredNotes
indexdefObjectYesAn object defining the lexicon columns to retrieve, where each key is a column name and each value is a cts.reference for the index.
qualifierStringNoOptional runtime alias for projected columns when plans need clearer naming.
systemColsStringNoOptional system columns (for example fragment ID) for downstream joins and diagnostics.

Setup

The examples rely on two additional indexes that are included in the llamaverse.

Path Range Index

A path range index on top-level id matches non-enveloped documents including wild llamas.

JSON Property Range Index

A JSON property range index on breed. In Admin UI terminology this is configured via element-style controls even for JSON nodes. Treat UI wording as implementation detail and always verify the actual index reference used in code.

Comparison to cts.values()

Start with a direct comparison to cts:values(). cts:values() returns distinct values only, regardless of how many fragments contain each value. You can filter that set, but you do not get fragment-linked rows directly.

op.fromLexicons() returns a row plan with fragment linkage exposed. The practical consequence is one row per fragment, not one row per unique value.

{
  "name": "Aaron",
  "breed": "Huacaya",
  "placeOfBirth": "Cusco, Peru",
  "secretPowerId": "d8839ba6-2b77-4bcc-9927-b86cdfecb9fb"
}
xquery version "1.0-ml";

cts:values(cts:element-reference(xs:QName("breed")))
'use strict';

const results = cts.values(cts.elementReference(xs.QName('breed'))).toArray();

({
	sample: 'optic/op-from-lexicons/assets/cts-values-comparison.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
});
Huacaya
Hybrid
Suri
xquery version "1.0-ml";
import module namespace op = "http://marklogic.com/optic" at "/MarkLogic/optic.xqy";

op:from-lexicons(
  map:entry("breed", cts:json-property-reference("breed"))
)
  => op:result()
'use strict';

const op = require('/MarkLogic/optic');

const results = op.fromLexicons({ breed: cts.jsonPropertyReference('breed') })
  .result();

({
  sample: 'optic/op-from-lexicons/assets/from-lexicons-breed.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
});

[
  {
  "breed": "Huacaya"
  }, 
  ... hundreds of other rows with Huacaya
  {
  "breed": "Huacaya"
  }, 
  {
  "breed": "Hybrid"
  }, 
  ... hundreds of other rows with Hybrid
  {
  "breed": "Suri"
  }, 
  {
  ... hundreds of other rows with Suri
  }
  .... thousands of rows in total
]

Example

xquery version "1.0-ml";
import module namespace op = "http://marklogic.com/optic" at "/MarkLogic/optic.xqy";

op:from-lexicons(
  map:entry("breed", cts:element-reference(xs:QName("breed")))
    => map:with("heightCm", cts:path-reference("/heightCm", ("type=int"))),
  (),
  op:fragment-id-col("fragmentId")
)
  => op:where(op:eq(op:col("breed"), "Suri"))
  => op:select(("fragmentId", "breed", "heightCm"))
  => op:limit(3)
  => op:result()
'use strict';

const op = require('/MarkLogic/optic');

const plan = op.fromLexicons({
  breed: cts.elementReference(xs.QName('breed')),
  heightCm: cts.pathReference('/heightCm', ['type=int'])
}, null, op.fragmentIdCol('fragmentId'))
  .where(op.eq(op.col('breed'), 'Suri'))
  .select(['fragmentId', 'breed', 'heightCm'])
  .limit(3);

const results = plan.result();

({
  sample: 'optic/op-from-lexicons/assets/from-lexicons-example.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
});

This plan retrieves llama IDs, names, and their fields from range indexes.

When to Choose op.fromLexicons()

Use op.fromLexicons() when fragment-linked index rows are the right starting point for joins, audits, or high-volume reporting.

Choose cts:values() for distinct-value summaries. Choose op.fromLexicons() when you need value plus fragment context in the same plan.

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!