Skip to content

NornicDB Plugin System ​

NornicDB features a plugin system that extends Cypher with APOC (Awesome Procedures On Cypher) functions. The APOC plugin provides 964 functions covering collections, text processing, math, graph algorithms, data import/export, and more.

Overview ​

The plugin system provides:

  • Dynamic Plugin Loading: Plugins are .so files loaded automatically at startup
  • APOC Plugin: Pre-built plugin with 964 functions included in all Docker images
  • Custom Plugins: Create your own plugins following the same interface
  • Configuration Control: Enable/disable via environment variables

Quick Start ​

Using APOC Functions ​

All Docker images include the APOC plugin pre-loaded:

cypher
// Collection functions
RETURN apoc.coll.sum([1, 2, 3, 4, 5])           // 15
RETURN apoc.coll.avg([1, 2, 3, 4, 5])           // 3.0
RETURN apoc.coll.flatten([[1,2], [3,4]])        // [1,2,3,4]

// Text functions
RETURN apoc.text.capitalize('hello world')      // "Hello world"
RETURN apoc.text.camelCase('hello_world')       // "helloWorld"
RETURN apoc.text.levenshteinDistance('cat', 'bat')  // 1

// Math functions
RETURN apoc.math.sqrt(16)                       // 4.0
RETURN apoc.math.sigmoid(0)                     // 0.5

// Scoring functions
RETURN apoc.scoring.cosine([1,0], [0,1])        // 0.0
RETURN apoc.scoring.jaccard([1,2,3], [2,3,4])   // 0.5

// Spatial functions
RETURN apoc.spatial.haversineDistance(40.7128, -74.0060, 34.0522, -118.2437)

// Create functions
RETURN apoc.create.uuid()                       // "550e8400-e29b-41d4-..."

Configuration ​

Environment Variables ​

bash
# Directory containing .so plugin files (default: /app/plugins in Docker)
NORNICDB_PLUGINS_DIR=/app/plugins

# Enable/disable plugin system
NORNICDB_PLUGINS_ENABLED=true

Docker Compose ​

yaml
services:
  nornicdb:
    image: timothyswt/nornicdb-arm64-metal:latest
    environment:
      - NORNICDB_PLUGINS_DIR=/app/plugins
    volumes:
      - ./custom-plugins:/app/plugins/custom  # Add custom plugins

Available Function Categories ​

The APOC plugin includes 964 functions across these categories:

CategoryCountDescription
apoc.coll46Collection operations (sum, avg, sort, flatten, union, etc.)
apoc.text41Text manipulation (capitalize, replace, distance, regex, etc.)
apoc.math45Mathematical operations (sqrt, trig, statistics, etc.)
apoc.convert24Type conversion (toFloat, toJson, toList, etc.)
apoc.date15Date/time handling (format, parse, add, etc.)
apoc.json18JSON operations (parse, stringify, path, merge, etc.)
apoc.util38Utilities (md5, sha256, uuid, compress, etc.)
apoc.agg15Aggregation (median, percentile, stdev, histogram, etc.)
apoc.algo9Graph algorithms (pageRank, dijkstra, etc.)
apoc.map25Map operations (merge, flatten, groupBy, etc.)
apoc.create19Node/relationship creation (node, relationship, uuid, etc.)
apoc.export14Data export (json, csv, cypher, graphML, etc.)
apoc.import19Data import (json, csv, xml, etc.)
apoc.load29Data loading (json, csv, jdbc, s3, kafka, etc.)
apoc.log25Logging (info, debug, warn, metrics, etc.)
apoc.node34Node operations (degree, labels, properties, etc.)
apoc.nodes22Multi-node operations (group, partition, connected, etc.)
apoc.rel29Relationship operations (type, properties, weight, etc.)
apoc.refactor20Graph refactoring (mergeNodes, renameLabel, etc.)
apoc.schema30Schema operations (indexes, constraints, etc.)
apoc.meta38Metadata (schema, stats, types, etc.)
apoc.neighbors6Neighbor traversal (atHop, bfs, dfs, etc.)
apoc.path9Path operations (expand, slice, etc.)
apoc.paths21Path finding (shortest, all, kShortest, etc.)
apoc.periodic10Periodic operations (iterate, commit, etc.)
apoc.search29Search operations (fulltext, fuzzy, regex, etc.)
apoc.scoring22Similarity scoring (cosine, jaccard, bm25, etc.)
apoc.spatial19Spatial operations (distance, bearing, geohash, etc.)
apoc.stats23Statistics (mean, median, correlation, etc.)
apoc.temporal26Temporal operations (format, parse, duration, etc.)
apoc.trigger24Trigger management (add, remove, enable, etc.)
apoc.warmup15Cache warmup (run, nodes, relationships, etc.)
apoc.xml23XML operations (parse, query, transform, etc.)
apoc.label27Label operations (add, remove, exists, etc.)
apoc.lock19Locking (nodes, relationships, etc.)
apoc.merge17Merge operations (node, relationship, etc.)
apoc.hashing18Hashing (md5, sha256, murmur, etc.)
apoc.graph15Graph operations (fromData, validate, etc.)
apoc.diff9Diff operations (nodes, maps, etc.)
apoc.cypher16Cypher utilities (run, parallel, etc.)
apoc.bitwise15Bitwise operations (and, or, xor, etc.)
apoc.atomic9Atomic operations (add, update, etc.)
apoc.number38Number formatting (format, parse, toHex, etc.)

Creating Custom Plugins ​

Plugin Interface ​

Create a Go file that exports a Plugin variable implementing the interface:

go
// my_plugin.go
package main

import "github.com/orneryd/nornicdb/apoc"

// Plugin is the exported symbol NornicDB loads
var Plugin = MyPlugin{}

type MyPlugin struct{}

func (p MyPlugin) Name() string    { return "myplugin" }
func (p MyPlugin) Version() string { return "1.0.0" }

func (p MyPlugin) Functions() map[string]apoc.FunctionInfo {
    return map[string]apoc.FunctionInfo{
        "apoc.myplugin.hello": {
            Handler:     Hello,
            Category:    "myplugin",
            Description: "Returns a greeting",
            Examples:    []string{"apoc.myplugin.hello('World') => 'Hello, World!'"},
        },
        "apoc.myplugin.double": {
            Handler:     Double,
            Category:    "myplugin",
            Description: "Doubles a number",
            Examples:    []string{"apoc.myplugin.double(21) => 42"},
        },
    }
}

func Hello(name string) string {
    return "Hello, " + name + "!"
}

func Double(n float64) float64 {
    return n * 2
}

Building Your Plugin ​

bash
# Build the plugin (must use same Go version as NornicDB)
go build -buildmode=plugin -o my-plugin.so my_plugin.go

# Copy to plugins directory
cp my-plugin.so /path/to/nornicdb/plugins/

Using Your Plugin ​

After restarting NornicDB, your functions are available:

cypher
RETURN apoc.myplugin.hello('World')   // "Hello, World!"
RETURN apoc.myplugin.double(21)       // 42

Startup Logs ​

On startup, NornicDB logs loaded plugins:

🔌 Loading Plugins from /app/plugins...
  ✓ apoc.so: 964 functions loaded (v1.0.0)
  ✓ my-plugin.so: 2 functions loaded (v1.0.0)
📦 Total: 966 plugin functions available

Building the APOC Plugin ​

From the NornicDB source:

bash
# Build using Makefile
make plugins

# Or manually
cd apoc/plugin-src/apoc
go build -buildmode=plugin -o ../../../apoc/built-plugins/apoc.so apoc_plugin.go

Docker Image Plugin Locations ​

All official Docker images include the pre-built APOC plugin:

ImagePlugins LocationFunctions
nornicdb-arm64-metal/app/plugins/apoc.so964
nornicdb-amd64-cuda/app/plugins/apoc.so964
nornicdb-amd64-cpu/app/plugins/apoc.so964

Troubleshooting ​

Plugin Not Loading ​

  1. Check plugin file exists and is readable:

    bash
    ls -la /app/plugins/
  2. Verify Go version compatibility (plugins must be built with same Go version):

    bash
    go version
  3. Check logs for errors:

    bash
    docker logs nornicdb 2>&1 | grep -i plugin

Function Not Found ​

  1. Check if function exists:

    cypher
    CALL apoc.help('coll.sum')
  2. Verify plugin loaded at startup (check logs)

Invalid ELF Header ​

This error means the plugin was built for a different architecture:

  • Rebuild the plugin for the target architecture (arm64 vs amd64)
  • Ensure you're using go build -buildmode=plugin with matching platform

Platform Support ​

PlatformPlugin SupportNotes
Linux (amd64)FullNative Go plugin support
Linux (arm64)FullNative Go plugin support
macOS (arm64)FullNative Go plugin support
macOS (amd64)FullNative Go plugin support
WindowsNoneGo plugins not supported

For Windows, build NornicDB with APOC functions compiled in (not as plugin).

Performance ​

  • Plugins load once at startup (~100ms for APOC)
  • Function calls have minimal overhead (direct function pointer)
  • No difference in performance between built-in and plugin functions

Security Considerations ​

  • Plugins run with the same permissions as NornicDB
  • Only load plugins from trusted sources
  • Plugin code has full system access
  • Use Docker volume mounts for isolation
  • Review plugin source code before deployment
Analytics privacy