RDF List Access Operations

This guide covers operations for reading elements from RDF lists. These operations allow you to inspect list contents without modifying the underlying structure.

What You'll Learn

  • How to read the first element of a list
  • How to iterate through all list elements
  • How to count list elements
  • How to extract slices of lists
  • How to access elements by index (nth0/nth1)

Operations Summary

OperationDescriptionTime Complexity
rdflist_peekGet first elementO(1)
rdflist_memberIterate all elementsO(n)
rdflist_lengthCount elementsO(n)
rdflist_listCollect all elements as arrayO(n)
rdflist_sliceExtract a range of elementsO(n)

rdflist_peek

Gets the first element (head) of an RDF list without removing it, or match it with the value in the variable when using as a match operator.

Syntax

Example: JavaScript
WOQL.lib().rdflist_peek(consSubject, valueVar)

Parameters

ParameterTypeDescription
consSubjectstringThe list head identifier
valueVarstringVariable to bind the first value

Example

Example: JavaScript
const query = WOQL.lib().rdflist_peek(listHead, "v:first_value");
const result = await client.query(query);

const firstValue = result.bindings[0]["first_value"];
console.log(firstValue["@value"]); // "Task A"

Use Cases

  • Preview: Check the first item without consuming it
  • Stack peek: Implement stack-like peek operations
  • Validation: Verify the head element before processing

rdflist_member

Traverses an RDF list and binds each element to a variable through unification. Returns multiple bindings, one for each element. Can be used to both match existing list elements and generate solutions.

Syntax

Example: JavaScript
WOQL.lib().rdflist_member(consSubject, valueVar)

Parameters

ParameterTypeDescription
consSubjectstringThe list head identifier
valueVarstringVariable to bind each element

Example

Example: JavaScript
const query = WOQL.lib().rdflist_member(listHead, "v:value");
const result = await client.query(query);

// Returns multiple bindings
const values = result.bindings.map(b => {
  const val = b["value"] || b["v:value"];
  return val?.["@value"] || val;
});

console.log(values); // ["Task A", "Task B", "Task C"]

Use Cases

  • Iteration: Process each element in the list
  • Search: Find elements matching criteria
  • Aggregation: Collect values for further processing

Combining with Other Queries

Example: JavaScript
// Find all tasks with high priority
const query = WOQL.and(
  WOQL.lib().rdflist_member(taskListHead, "v:task_id"),
  WOQL.triple("v:task_id", "priority", "v:priority"),
  WOQL.greater("v:priority", 5)
);

rdflist_length

Counts the number of elements in an RDF list, or match that the number of elements match a variable.

Syntax

Example: JavaScript
WOQL.lib().rdflist_length(consSubject, lengthVar)

Parameters

ParameterTypeDescription
consSubjectstringThe list head identifier
lengthVarstringVariable to bind the count

Example

Example: JavaScript
const query = WOQL.lib().rdflist_length(listHead, "v:count");
const result = await client.query(query);

const length = parseInt(result.bindings[0]["count"]["@value"]);
console.log(`List has ${length} elements`);

Use Cases

  • Validation: Check list size constraints
  • Pagination: Calculate total pages
  • Capacity checks: Verify list doesn't exceed limits

rdflist_list

Collects all elements from an RDF list into a single array in one binding. Can also be used to verify that an RDF list matches a given array.

Syntax

Example: JavaScript
WOQL.lib().rdflist_list(consSubject, listVar)

Parameters

ParameterTypeDescription
consSubjectstringThe list head identifier
listVarstringVariable to bind the collected array

Example

Example: JavaScript
const query = WOQL.lib().rdflist_list(listHead, "v:all_items");
const result = await client.query(query);

const items = result.bindings[0]["all_items"];
console.log(items); // [{@value: "A"}, {@value: "B"}, {@value: "C"}]

// Extract values
const values = items.map(item => item?.["@value"] || item);
console.log(values); // ["A", "B", "C"]

Use Cases

  • Export: Get all list items in one result
  • Comparison: Compare entire lists
  • Serialization: Convert list to JSON array

Difference from rdflist_member

OperationReturnsBindings
rdflist_memberOne element per bindingMultiple bindings
rdflist_listAll elements as arraySingle binding

rdflist_slice

Extracts a range of elements from an RDF list. Uses 0-based indexing and an exclusive end. Think of the positions to match to be the positions "between" the elements. 0 is before the first element, 1 is after the first element, etc. Thus, to slice the first element, slice between 0 and 1.

Syntax

Example: JavaScript
WOQL.lib().rdflist_slice(consSubject, start, end, resultVar)

Parameters

ParameterTypeDescription
consSubjectstringThe list head identifier
startnumberStart index (0-based, inclusive)
endnumberEnd index (exclusive)
resultVarstringVariable to bind the slice array

Examples

Example: JavaScript
// List: [A, B, C, D]

// Get first two elements: slice(0, 2) → [A, B]
const first2 = WOQL.lib().rdflist_slice(listHead, 0, 2, "v:result");

// Get middle elements: slice(1, 3) → [B, C]
const middle = WOQL.lib().rdflist_slice(listHead, 1, 3, "v:result");

// Get last two elements: slice(2, 4) → [C, D]
const last2 = WOQL.lib().rdflist_slice(listHead, 2, 4, "v:result");

// Single element: slice(1, 2) → [B]
const single = WOQL.lib().rdflist_slice(listHead, 1, 2, "v:result");

// Empty slice when start >= end: slice(2, 2) → []
const empty = WOQL.lib().rdflist_slice(listHead, 2, 2, "v:result");

Use Cases

  • Pagination: Get a page of results
  • Preview: Show first N items
  • Windowing: Process data in chunks

Accessing Elements by Index

You can use slice instead of nth0 or nth1 operations for single items.

Using Slice for Index Access

Example: JavaScript
// Get element at index 2 (0-based)
const getAt2 = WOQL.lib().rdflist_slice(listHead, 2, 3, "v:element");
const result = await client.query(getAt2);
const element = result.bindings[0]["element"][0]; // First item of single-element array

Using Path Queries instead, for manual parsing

Notice that WOQL.path() uses regex style matching (inclusive), whereas slice uses exclusive matching, like in Javascript.

Example: JavaScript
// Access elements by path traversal
// Path {n,n} traverses exactly n rdf:rest links
const pathQuery = WOQL.and(
  WOQL.path(listHead, "rdf:rest{2,2}", "v:cell"),  // Skip 2 cells
  WOQL.triple("v:cell", "rdf:first", "v:value")    // Get value
);

Zero-Based vs One-Based Indexing

  • 0-based (nth0): First element is at index 0
  • 1-based (nth1): First element is at index 1

Use slice with appropriate indices:

  • nth0(2) = slice(2, 3)[0]
  • nth1(2) = slice(1, 2)[0]

Complete Example: List Analysis

List head in the example below is the object of a triple from a list. A list defined on a document/record in TerminusDB will have a triple such as triple("v:docId", "list", "v:listHeadId"). The listHeadId would be what is called a Cons, an rdf:List "construct" that is the start of a list.

Example: JavaScript
import { WOQLClient, WOQL } from "@terminusdb/terminusdb-client";

async function analyzeList(client, listHead) {
  // Get list length
  const lengthQuery = WOQL.lib().rdflist_length(listHead, "v:len");
  const lengthResult = await client.query(lengthQuery);
  const length = parseInt(lengthResult.bindings[0]["len"]["@value"]);
  console.log(`List length: ${length}`);
  
  if (length === 0) {
    console.log("List is empty");
    return;
  }
  
  // Get first element
  const peekQuery = WOQL.lib().rdflist_peek(listHead, "v:first");
  const peekResult = await client.query(peekQuery);
  console.log(`First element: ${peekResult.bindings[0]["first"]["@value"]}`);
  
  // Get all elements
  const listQuery = WOQL.lib().rdflist_list(listHead, "v:all");
  const listResult = await client.query(listQuery);
  const allItems = listResult.bindings[0]["all"];
  console.log("All elements:", allItems.map(i => i["@value"]));
  
  // Get first half
  const halfLength = Math.ceil(length / 2);
  const sliceQuery = WOQL.lib().rdflist_slice(listHead, 0, halfLength, "v:half");
  const sliceResult = await client.query(sliceQuery);
  const firstHalf = sliceResult.bindings[0]["half"];
  console.log("First half:", firstHalf.map(i => i["@value"]));
}

Working with Document References in Lists

Example: JavaScript
// Create tasks
await client.addDocument([
  { "@type": "Task", "@id": "Task/1", title: "Fix bug", priority: 1 },
  { "@type": "Task", "@id": "Task/2", title: "Update docs", priority: 2 }
]);

// Read task details from list
const detailsQuery = WOQL.and(
  WOQL.lib().rdflist_member(taskListHead, "v:task_id"),
  WOQL.triple("v:task_id", "title", "v:title"),
  WOQL.triple("v:task_id", "priority", "v:priority")
);

const details = await client.query(detailsQuery);
// Returns: [{task_id: "Task/1", title: "Fix bug", priority: 1}, ...]

Read More

Was this helpful?