Skip to content

NornicDB Complete Functions Index ​

documentation with real-world examples

Last Updated: November 25, 2025


Quick Navigation ​

Detailed Function Docs - Complete guides with examples Memory Decay System - How memory fading works Status: 52 functions documented (100% coverage)


All Functions by Category ​

Node & Relationship Functions (11 functions) ​

FunctionWhat It DoesExample
id(n)Get unique IDMATCH (n) RETURN id(n)
elementId(n)Neo4j-compatible IDRETURN elementId(n)
labels(n)Get node labels/typesRETURN labels(n)
type(r)Get relationship typeMATCH ()-[r]->() RETURN type(r)
keys(n)List property namesRETURN keys(n)
properties(n)Get all propertiesRETURN properties(n)
startNode(r)Get relationship start nodeRETURN startNode(r)
endNode(r)Get relationship end nodeRETURN endNode(r)
nodes(path)Get nodes in pathRETURN nodes(path)
relationships(path)Get rels in pathRETURN relationships(path)
exists(n.prop)Check if property existsWHERE exists(n.email)

String Functions (20 functions) ​

FunctionWhat It DoesExample
toString(val)Convert to stringRETURN toString(42)
toLower(s)Convert to lowercaseRETURN toLower("HELLO")
toUpper(s)Convert to UPPERCASERETURN toUpper("hello")
trim(s)Remove edge whitespaceRETURN trim(" hi ")
ltrim(s)Trim left sideRETURN ltrim(" hi")
rtrim(s)Trim right sideRETURN rtrim("hi ")
replace(s, find, repl)Find & replaceRETURN replace("cat", "c", "b")
split(s, delim)Split into listRETURN split("a,b,c", ",")
substring(s, start, len)Extract substringRETURN substring("hello", 0, 3)
left(s, n)First n charactersRETURN left("hello", 2)
right(s, n)Last n charactersRETURN right("hello", 2)
size(s)String/list lengthRETURN size("hello")
char_length(s)Character countRETURN char_length("hi")
normalize(s)Unicode normalizationRETURN normalize(s)
btrim(s, chars)Trim specific charsRETURN btrim("!!hi!!", "!")

The string.* namespace (Cypher 25 functions, also accepted under Cypher 5):

FunctionWhat It DoesExample
string.indexOf(s, value)Character index of value in s, or -1RETURN string.indexOf("hello", "l")
string.join(list, delimiter)Join a list of stringsRETURN string.join(["a", "b"], "-")
string.regexReplace(s, re, repl)Replace every match of a regular expressionRETURN string.regexReplace("a b", "\s+", " ")

Type Conversion Functions (4 functions) ​

FunctionWhat It DoesExample
toInteger(val)Convert to integerRETURN toInteger("42")
toInt(val)Alias for toIntegerRETURN toInt("42")
toFloat(val)Convert to decimalRETURN toFloat("3.14")
toBoolean(val)Convert to true/falseRETURN toBoolean("true")

Mathematical Functions (7 functions) ​

FunctionWhat It DoesExample
abs(x)Absolute valueRETURN abs(-5)
ceil(x)Round upRETURN ceil(3.2)
floor(x)Round downRETURN floor(3.8)
round(x)Round normallyRETURN round(3.5)
sign(x)Get sign (-1/0/1)RETURN sign(-5)
sqrt(x)Square rootRETURN sqrt(16)
rand()Random 0-1RETURN rand()

Trigonometric Functions (11 functions) ​

FunctionWhat It DoesExample
sin(x)SineRETURN sin(radians(90))
cos(x)CosineRETURN cos(radians(0))
tan(x)TangentRETURN tan(radians(45))
cot(x)CotangentRETURN cot(radians(45))
asin(x)Arc sineRETURN asin(0.5)
acos(x)Arc cosineRETURN acos(0.5)
atan(x)Arc tangentRETURN atan(1)
atan2(y, x)2-arg arc tangentRETURN atan2(y, x)
radians(deg)Degrees→radiansRETURN radians(180)
degrees(rad)Radians→degreesRETURN degrees(3.14)
haversin(x)HaversineRETURN haversin(x)

Advanced Math Functions (4 functions) ​

FunctionWhat It DoesExample
exp(x)e^xRETURN exp(1)
log(x)Natural logRETURN log(2.718)
log10(x)Base-10 logRETURN log10(100)
pi()π constantRETURN pi()
e()e constantRETURN e()

List Functions (17 functions) ​

FunctionWhat It DoesExample
size(list)List lengthRETURN size([1,2,3])
head(list)First elementRETURN head([1,2,3])
last(list)Last elementRETURN last([1,2,3])
tail(list)All except firstRETURN tail([1,2,3])
reverse(list)Reverse orderRETURN reverse([1,2,3])
range(start, end, step)Create number sequenceRETURN range(1, 10, 2)
coalesce(v1, v2, ...)First non-null valueRETURN coalesce(null, 5, 10)
reduce(...)Reduce list to valueSee examples below
isEmpty(x)Check if emptyRETURN isEmpty([])

The coll.* functions of Cypher 25 (Neo4j 2026.09; NornicDB has them in Cypher 5 statements too). They order values as ORDER BY does (null after everything) and tell them apart as DISTINCT does (1 and 1.0 are one value). A null list, index or depth gives null.

FunctionWhat It DoesExample
coll.distinct(list)Duplicates removed, first keptRETURN coll.distinct([1, 1.0, 2]) → [1, 2]
coll.flatten(list [, depth])Nested lists spliced in, depth levels (default 1)RETURN coll.flatten([1, [2, [3]]], 2) → [1, 2, 3]
coll.indexOf(list, value)Index of the first equal item, or -1RETURN coll.indexOf([1, 2], 2) → 1
coll.insert(list, index, value)value inserted before list[index] (0 to size)RETURN coll.insert([1, 3], 1, 2)
coll.remove(list, index)list without list[index]RETURN coll.remove([1, 2, 3], 0)
coll.max(list) / coll.min(list)Greatest / least item in ORDER BY orderRETURN coll.max([3, 1, 2]) → 3
coll.sort(list)Sorted in ORDER BY orderRETURN coll.sort([3, 'a', 1]) → ['a', 1, 3]

An index or depth out of range, and coll.remove on an empty list, are ArgumentErrors, as in Neo4j.

Vector Functions (2 functions) ​

FunctionWhat It DoesExample
vector.similarity.cosine(v1, v2)Cosine similarity, in [0, 1]RETURN vector.similarity.cosine([1,2,3], [2,3,4])
vector.similarity.euclidean(v1, v2)Euclidean similarity, in [0, 1]RETURN vector.similarity.euclidean([0,0], [3,4])

Both return Neo4j's scores, bit for bit: cosine is max((1 + cos) / 2, 0) (1 for the same direction, 0.5 for orthogonal vectors, 0 for opposite ones) and euclidean is 1 / (1 + d²) (1 for equal vectors), computed in float32. db.index.vector.queryNodes and queryRelationships score on the same scale for COSINE and EUCLIDEAN indexes (a dot index, a NornicDB similarity, scores the dot product). Null in, null out; an argument that isn't a list is a TypeError; an empty list, a list holding a non-number or a non-finite number, a zero vector (cosine) or vectors of different dimensions are an ArgumentError, as in Neo4j.

VECTOR and UUID values (Cypher 25). vector(value, dimension, coordinateType) builds a VECTOR of INTEGER64 (INTEGER), INTEGER32, INTEGER16, INTEGER8, FLOAT64 (FLOAT) or FLOAT32 coordinates from a list of numbers or its text; uuid() is a random version 7 UUID. Both can be stored as properties, compared with =, sorted, and tested with IS :: VECTOR<INTEGER>(3) / IS :: UUID. A vector is not a list: toIntegerList, toFloatList and size read it. Bolt 5 clients receive both as the placeholder map {reason: 'UNKNOWN_TYPE', originalType: 'VECTOR(3, INTEGER64)'} (or 'UUID'), as Neo4j sends them; the HTTP API writes a UUID as its text.

FunctionWhat It DoesExample
vector(value, dimension, type)A VECTORRETURN vector([1, 2, 3], 3, INTEGER)
vector_dimension_count(v)Its dimensionRETURN vector_dimension_count(vector([1, 2], 2, FLOAT))
vector_distance(a, b, metric)Distance by EUCLIDEAN, EUCLIDEAN_SQUARED, MANHATTAN, COSINE, DOT or HAMMINGRETURN vector_distance(vector([1, 2], 2, FLOAT), vector([2, 4], 2, FLOAT), EUCLIDEAN)
vector_norm(v, metric)Distance to the origin by EUCLIDEAN or MANHATTANRETURN vector_norm(vector([3, 4], 2, INTEGER), EUCLIDEAN)
uuid() / uuid(text) / uuid(msb, lsb)A UUIDRETURN toString(uuid(1, 2))
uuid.mostSignificantBits(u) / uuid.leastSignificantBits(u)Its halves as integersRETURN uuid.mostSignificantBits(uuid())
uuid.v5(namespace, name)The version 5 (name-based) UUID of name in namespace (a UUID or its text): the same arguments always give the same UUID, so MERGE can deduplicate on it. A NornicDB extension.RETURN toString(uuid.v5('6ba7b810-9dad-11d1-80b4-00c04fd430c8', 'python.org'))

Kalman Filter Functions (10 functions) ​

Real-time signal filtering and prediction for time series data. Perfect for smoothing noisy sensor readings, tracking market sentiment, or predicting trends.

FunctionWhat It DoesExample
kalman.init(config?)Create basic filter stateRETURN kalman.init()
kalman.process(val, state, target?)Filter a measurementkalman.process(23.5, s.state)
kalman.predict(state, steps)Predict future valuekalman.predict(s.state, 5)
kalman.state(state)Get current estimatekalman.state(s.state)
kalman.reset(state)Reset filterkalman.reset(s.state)
kalman.velocity.init(pos?, vel?)Create trend-tracking filterkalman.velocity.init()
kalman.velocity.process(val, state)Filter with velocity trackingReturns {value, velocity, state}
kalman.velocity.predict(state, steps)Predict with momentumkalman.velocity.predict(s.state, 5)
kalman.adaptive.init(config?)Create auto-switching filterkalman.adaptive.init()
kalman.adaptive.process(val, state)Filter with auto mode-switchReturns {value, mode, state}

Text Location (1 function, a NornicDB extension) ​

text.locate(text, quote, options) returns {start, end}, the span of a quote's best occurrence in text in code points (substring(text, start, end - start) is the passage), or null. The quote's words match in order, as a reader copies a quote: without case; with any run of whitespace, JSON escapes (\n, \r, \t, as a JSON file's one-line body has them) or a reply's > markers after a line break between them (a > in the quote matches one literally); typographic and plain quotation marks (', "), apostrophes and dashes alike; markdown emphasis (*, **, _, __) and link markup ([label](/api-reference/cypher-functions/target)) allowed around a word, never inside one, so filename doesn't match file_name. The span is the text's own, markup around its first and last words included. In the quote, a copied line label (12: ) and JSON escapes are dropped.

OptionMeaning
lineThe 1-based line the quote was cited on: the occurrence starting on it wins, else the nearest within tolerance lines (the lower line first on a tie), else null. A line that isn't one of the text's is null. Without it, the first occurrence wins.
toleranceLines around line an occurrence may start on (default 3).
from, toThe code-point range the occurrence must lie in.
cypher
MATCH (s:Source {id: $id})
RETURN text.locate(s.text, $quote, {line: $line, from: $partStart, to: $partEnd}) AS span

To place many quotes in one long text passed as a parameter, bind it once (WITH $text AS t UNWIND $citations AS c RETURN text.locate(t, c.quote, {line: c.line})): a string parameter used directly in the per-row expression is re-read on every row.

Text intervals and line positions in Cypher ​

Spans stored as parallel lists (starts, ends and metadata such as labels or roles, half-open [start, end) in code points, as substring and text.locate count) need no function of their own. These statements return the same rows in Neo4j.

Run the partition statement after a MATCH that binds s, for example MATCH (s:Source {id: $id}), with parameters start and end. Its lists may be unordered and overlapping: the interval with the earliest start owns the overlap, with the lower list index winning equal starts. A later interval contributes only its uncovered suffix. Empty intervals are ignored; empty or absent lists leave the whole span as 'own'. The extra empty interval in the statement preserves a row for that case.

cypher
// Intervals overlapping [start, stop), clipped to it, in list order with index and metadata;
// an empty span [start, start) stands for [start, start + 1)
WITH s, $start AS start, CASE WHEN $end > $start THEN $end ELSE $start + 1 END AS stop
RETURN [i IN range(0, size(coalesce(s.starts, [])) - 1)
        WHERE s.starts[i] < stop AND start < s.ends[i]
        | {index: i, start: CASE WHEN start > s.starts[i] THEN start ELSE s.starts[i] END,
           end: CASE WHEN stop < s.ends[i] THEN stop ELSE s.ends[i] END, label: s.labels[i]}] AS overlaps

// [start, end) split into the intervals' clipped parts with their role, gaps as 'own'
WITH s, $start AS start, $end AS end
UNWIND [i IN range(0, size(coalesce(s.starts, [])) - 1) |
        {start: s.starts[i], end: s.ends[i], role: s.roles[i], index: i}]
       + [{start: end, end: end, index: -1}] AS part
WITH s, start, end, part ORDER BY part.start, part.index
WITH s, start, end, collect(part) AS intervals
WITH start, end, reduce(acc = {position: start, parts: []}, part IN intervals |
  CASE WHEN start >= end OR part.start >= part.end OR part.start >= end OR part.end <= acc.position THEN acc
  ELSE {position: CASE WHEN part.end < end THEN part.end ELSE end END,
        parts: acc.parts
          + CASE WHEN acc.position < part.start
                 THEN [{start: acc.position, end: part.start, role: 'own'}]
                 ELSE [] END
          + [{start: CASE WHEN part.start > acc.position THEN part.start ELSE acc.position END,
              end: CASE WHEN part.end < end THEN part.end ELSE end END, role: part.role}]}
  END) AS acc
RETURN acc.parts + CASE WHEN acc.position < end THEN [{start: acc.position, end: end, role: 'own'}] ELSE [] END AS parts

// The 1-based line, 0-based column and line text at a code-point offset
WITH text, offset, substring(text, 0, offset) AS before
WITH text, before, size(before) - size(replace(before, '\n', '')) AS breaks
RETURN breaks + 1 AS line, size(last(split(before, '\n'))) AS column, split(text, '\n')[breaks] AS context

// A span's lines as "n: line", numbered from first ('' gives "first: ")
WITH split(substring(text, $start, $end - $start), '\n') AS lines, $first AS first
RETURN reduce(out = '', i IN range(0, size(lines) - 1) |
  out + CASE WHEN i = 0 THEN '' ELSE '\n' END + toString(first + i) + ': ' + lines[i]) AS numbered

Each overlap list scans all intervals, so a span costs O(intervals). For many spans over one source, bind the lists once (WITH s.starts AS starts, s.ends AS ends UNWIND $spans AS q …).

APOC digests ​

apoc.util.sha256(values), apoc.util.sha1(values) and apoc.util.md5(values) are built in. They return the lower-case hex digest of the values' Java string forms concatenated; null list elements add nothing. For example, apoc.util.sha256(['a', 'b', null, 'c']) hashes the UTF-8 text abc. The bundled APOC handlers use the same implementation.

Date/Time Functions (4 functions) ​

FunctionWhat It DoesExample
timestamp()Current Unix timestamp (ms)RETURN timestamp()
datetime()Current datetimeRETURN datetime()
date()Current dateRETURN date()
time()Current timeRETURN time()

Null/Check Functions (3 functions) ​

FunctionWhat It DoesExample
isEmpty(x)Check if emptyRETURN isEmpty("")
isNaN(x)Check if not-a-numberRETURN isNaN(0/0)
nullIf(v1, v2)Return null if equalRETURN nullIf(5, 5)

Aggregation Functions (2 functions) ​

FunctionWhat It DoesExample
count(x)Count itemsMATCH (n) RETURN count(n)
length(path)Path lengthRETURN length(path)

Utility Functions (2 functions) ​

FunctionWhat It DoesExample
randomUUID()Generate UUIDRETURN randomUUID()
rand()Random number 0-1RETURN rand()

Real-World Example Collections ​

Example 1: Memory Search with Decay ​

cypher
// Find strong memories about a topic
MATCH (m:Memory)
WHERE m.content CONTAINS "database"
  AND decayScore(m) > 0.6
RETURN m.title,
       decayScore(m),
       m.accessCount,
       m.tier
ORDER BY decayScore(m) DESC
LIMIT 10

Example 2: Data Cleaning ​

cypher
// Clean up user input
MATCH (user:User)
SET user.email = toLower(trim(user.email)),
    user.name = trim(user.name)
WHERE user.email CONTAINS " " OR user.email <> toLower(user.email)
RETURN count(user) AS cleanedCount

Example 2b: Identity Match Keys ​

Compare names and identifiers whatever their width, case, spacing or script of digits, in plain Cypher: NFKC, lower case (with the letters lower case leaves apart, such as ß, folded too), whitespace runs as one space, decimal digits as ASCII through a map the caller passes, and -./ dropped from a key of digits only.

cypher
// $digits maps each non-ASCII decimal digit to its ASCII digit, e.g. {`٢`: '2', `3`: '3', …}
WITH replace(replace(toLower(normalize($raw, NFKC)), 'ß', 'ss'), 'ς', 'σ') AS folded
WITH trim(string.regexReplace(reduce(out = '', c IN split(folded, '') | out + coalesce($digits[c], c)), '\s+', ' ')) AS k
RETURN CASE WHEN k =~ '[0-9./-]+' THEN string.regexReplace(k, '[-./]', '') ELSE k END AS key
// "  MÜLLER   Straße 1" → "müller strasse 1";  "١٢٣-٤٥٦/٧٨" → "12345678"

Example 3: Calculate Distances ​

cypher
// Find nearby locations using Pythagorean theorem
MATCH (loc1:Location), (loc2:Location)
WHERE id(loc1) < id(loc2)
WITH loc1, loc2,
     sqrt(pow(loc1.x - loc2.x, 2) + pow(loc1.y - loc2.y, 2)) AS distance
WHERE distance < 10
RETURN loc1.name, loc2.name, round(distance * 100) / 100 AS distanceKm
ORDER BY distance

Example 4: Text Processing ​

cypher
// Parse and normalize tags
MATCH (post:Post)
WITH post,
     [tag IN split(toLower(post.tagString), ",") | trim(tag)] AS cleanTags
SET post.tags = cleanTags
RETURN count(post) AS processed
cypher
// Find memories similar to a query embedding
MATCH (m:Memory)
WHERE m.embedding IS NOT NULL
WITH m, vector.similarity.cosine(m.embedding, $queryEmbedding) AS similarity
WHERE similarity > 0.8
RETURN m.content,
       similarity,
       decayScore(m),
       similarity * decayScore(m) AS combinedScore
ORDER BY combinedScore DESC
LIMIT 5

Example 6: Statistical Analysis ​

cypher
// Analyze decay score distribution by label
MATCH (m:KnowledgeFact)
WITH labels(m)[0] AS label,
     count(m) AS total,
     avg(decayScore(m)) AS avgScore,
     min(decayScore(m)) AS minScore,
     max(decayScore(m)) AS maxScore
RETURN label, total,
       round(avgScore * 100) / 100,
       round(minScore * 100) / 100,
       round(maxScore * 100) / 100

Example 7: Conditional Logic with Coalesce ​

cypher
// Handle missing data gracefully
MATCH (user:User)
RETURN user.name,
       coalesce(user.email, user.phone, "No contact info") AS contact,
       coalesce(user.age, 0) AS age

Example 8: Generate Sequences ​

cypher
// Create pagination links
RETURN [page IN range(1, 10) |
        "https://example.com/page/" + toString(page)] AS pageLinks

Example 9: Complex String Manipulation ​

cypher
// Format display names
MATCH (person:Person)
WITH person,
     split(person.fullName, " ") AS nameParts
RETURN person.fullName,
       left(nameParts[0], 1) + ". " + last(nameParts) AS shortName,
       toUpper(left(nameParts[0], 1) + left(last(nameParts), 1)) AS initials

Example 10: Trigonometry for Geo-coordinates ​

cypher
// Haversine formula for Earth distance
MATCH (p1:Place), (p2:Place)
WITH p1, p2,
     radians(p1.lat) AS lat1, radians(p1.lon) AS lon1,
     radians(p2.lat) AS lat2, radians(p2.lon) AS lon2
WITH p1, p2,
     haversin(lat2 - lat1) + cos(lat1) * cos(lat2) * haversin(lon2 - lon1) AS h
RETURN p1.name, p2.name,
       2 * 6371 * asin(sqrt(h)) AS distanceKm

Example 11: Real-Time News Sentiment → Stock Prediction (Kalman Filter) ​

An LLM watches the Associated Press news feed in real-time, scoring each headline's market sentiment (-1.0 to +1.0). The Kalman filter smooths these noisy signals to predict stock movements.

cypher
// Step 1: Create stock trackers with Kalman filtering
UNWIND ["AAPL", "MSFT", "GOOGL", "TSLA", "NVDA"] AS symbol
CREATE (s:Stock {
    symbol: symbol,
    kalmanState: kalman.velocity.init(),  // Track trends
    sentiment: 0.0,
    momentum: 0.0
})

// Step 2: LLM processes AP news headline and scores sentiment
// headline: "Apple announces record iPhone sales in China"
// $symbol = "AAPL", $sentimentScore = 0.72

// Step 3: Process the sentiment score through Kalman filter
MATCH (s:Stock {symbol: $symbol})
WITH s, kalman.velocity.process($sentimentScore, s.kalmanState) AS result
SET s.kalmanState = result.state,
    s.sentiment = result.value,
    s.momentum = result.velocity,
    s.lastUpdate = timestamp()
RETURN s.symbol,
       round(result.value * 100) / 100 AS smoothedSentiment,
       round(result.velocity * 100) / 100 AS sentimentTrend,
       CASE
           WHEN result.velocity > 0.1 THEN "📈 BULLISH"
           WHEN result.velocity < -0.1 THEN "📉 BEARISH"
           ELSE "➡️ NEUTRAL"
       END AS signal

// Step 4: Predict sentiment 5 time-steps ahead for all stocks
MATCH (s:Stock)
WHERE s.kalmanState IS NOT NULL
RETURN s.symbol,
       round(s.sentiment * 100) / 100 AS currentSentiment,
       round(s.momentum * 100) / 100 AS trend,
       round(kalman.velocity.predict(s.kalmanState, 5) * 100) / 100 AS predictedSentiment,
       CASE
           WHEN kalman.velocity.predict(s.kalmanState, 5) > s.sentiment + 0.15 THEN "🚀 BUY SIGNAL"
           WHEN kalman.velocity.predict(s.kalmanState, 5) < s.sentiment - 0.15 THEN "⚠️ SELL SIGNAL"
           ELSE "HOLD"
       END AS recommendation
ORDER BY abs(s.momentum) DESC

// Step 5: Find stocks about to cross sentiment threshold
MATCH (s:Stock)
WITH s,
     s.sentiment AS current,
     kalman.velocity.predict(s.kalmanState, 3) AS predicted
WHERE current < 0.7 AND predicted >= 0.7  // About to go strongly bullish
RETURN s.symbol, current, predicted, "🎯 BREAKOUT CANDIDATE" AS alert

Example 12: IoT Sensor Smoothing with Kalman ​

cypher
// Initialize temperature sensors with Kalman filtering
CREATE (s:Sensor {
    id: "greenhouse-temp-1",
    location: "Zone A",
    kalmanState: kalman.init({measurementNoise: 50.0})
})

// Process incoming temperature reading and smooth it
MATCH (s:Sensor {id: $sensorId})
WITH s, kalman.process($rawTemperature, s.kalmanState, 25.0) AS result
SET s.kalmanState = result.state,
    s.temperature = result.value,
    s.lastReading = timestamp()
RETURN s.id,
       $rawTemperature AS raw,
       round(result.value * 10) / 10 AS smoothed

// Alert on predicted overheating (predict 10 readings ahead)
MATCH (s:Sensor)
WHERE kalman.predict(s.kalmanState, 10) > 35.0
RETURN s.id, s.location,
       round(kalman.predict(s.kalmanState, 10) * 10) / 10 AS predictedTemp,
       "⚠️ Predicted overheat in ~10 readings" AS alert

Example 13: Adaptive Kalman for Volatile Time Series ​

cypher
// Use adaptive filter for crypto (high volatility) - auto-switches modes
CREATE (c:Crypto {
    symbol: "BTC",
    kalmanState: kalman.adaptive.init({
        trendThreshold: 0.05,   // Switch to velocity mode on 5% trend
        hysteresis: 5           // Quick adaptation
    })
})

// Process price data - filter auto-switches between smoothing and tracking
MATCH (c:Crypto {symbol: $symbol})
WITH c, kalman.adaptive.process($price, c.kalmanState) AS result
SET c.kalmanState = result.state,
    c.price = result.value,
    c.filterMode = result.mode
RETURN c.symbol,
       round(result.value) AS filteredPrice,
       result.mode AS currentMode,
       CASE result.mode
           WHEN "velocity" THEN "📊 Trending market - tracking momentum"
           ELSE "📉 Stable market - smoothing noise"
       END AS interpretation

Function Categories by Use Case ​

Data Inspection ​

  • id(), labels(), type(), keys(), properties()

Data Cleaning ​

  • trim(), toLower(), toUpper(), replace(), split()

Type Safety ​

  • toInteger(), toFloat(), toString(), toBoolean()

Analytics ​

  • count(), avg(), sum(), min(), max()

Math & Stats ​

  • abs(), ceil(), floor(), round(), sqrt(), pow()

Spatial/Geo ​

  • sin(), cos(), haversin(), atan2(), sqrt() (for distances)

AI/ML Features ​

  • vector.similarity.cosine(), vector.similarity.euclidean()

Signal Processing & Prediction ​

  • kalman.init(), kalman.process(), kalman.predict()
  • kalman.velocity.init(), kalman.velocity.process(), kalman.velocity.predict()
  • kalman.adaptive.init(), kalman.adaptive.process()

Memory Management ​


Performance Notes ​

Fast Functions (< 1μs) ​

  • id(), labels(), type()
  • toString(), toInteger(), toFloat()
  • toLower(), toUpper()

Medium Functions (1-10μs) ​

  • trim(), replace(), split()
  • abs(), ceil(), floor(), round()

Slower Functions (> 10μs) ​

  • sin(), cos(), tan() and other trig functions
  • sqrt(), exp(), log()
  • vector.similarity.*() - depends on vector size

Tips for Performance ​

  1. Cache computed values instead of recalculating
  2. Use indexes for WHERE clauses before function calls
  3. Batch operations instead of per-node function calls
  4. Pre-compute expensive math when possible

Common Patterns ​

cypher
MATCH (n)
WHERE toLower(n.name) = toLower($searchTerm)
RETURN n

Pattern: Safe Property Access ​

cypher
MATCH (n)
RETURN coalesce(n.optionalProperty, "default value") AS prop

Pattern: Parse CSV Data ​

cypher
MATCH (n:RawData)
WITH n, split(n.csvLine, ",") AS fields
CREATE (p:ParsedData {
    field1: trim(fields[0]),
    field2: toInteger(trim(fields[1])),
    field3: toFloat(trim(fields[2]))
})

Pattern: Calculate Age ​

cypher
MATCH (person:Person)
RETURN person.name,
       floor((timestamp() - person.birthTimestamp) / (365.25 * 24 * 60 * 60 * 1000)) AS age
cypher
MATCH (doc:Document)
WHERE doc.embedding IS NOT NULL
WITH doc, vector.similarity.cosine(doc.embedding, $queryVector) AS score
WHERE score > 0.75
RETURN doc.title, score
ORDER BY score DESC
LIMIT 10

db.index.vector.queryNodes — disabled-database behaviour ​

When the procedure is called against a database whose db.nornic.search.vector.enabled setting is false (or whose global NORNICDB_SEARCH_VECTOR_ENABLED alternative is false, with the per-database override winning):

  • The procedure returns zero rows — the same shape as a query against an empty index.
  • A WARN-level log line is emitted with subsystem=vector_search and the index_name:
    db.index.vector.queryNodes called against vector-disabled database — returning empty result
  • The Cypher query as a whole does not error — composite queries that gracefully handle empty vector results continue to succeed. This makes the procedure safe to call from query plans that may target either vector-enabled or vector-disabled databases.

To switch behaviour, flip the master switch via:

bash
curl -X PUT http://localhost:7474/admin/databases/<db>/config \
  -H "Content-Type: application/json" \
    -d '{"overrides": {"db.nornic.search.vector.enabled": "true"}}'

See Per-Database Search Index Flags.

References & Further Reading ​

These sources describe general concepts and Neo4j. NornicDB behavior can differ; use the descriptions above for NornicDB-specific details.

Memory Models ​

Mathematical Functions ​

Vector Similarity ​

Neo4j Cypher Reference ​


Documentation Status: Complete

Functions Documented: 62/62 (100%)

Examples Provided: 160+

Last Updated: November 29, 2025

Analytics privacy