Skip to content

NornicDB Plugin System

NornicDB features a powerful 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:

// 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

# 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

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:

Category Count Description
apoc.coll 46 Collection operations (sum, avg, sort, flatten, union, etc.)
apoc.text 41 Text manipulation (capitalize, replace, distance, regex, etc.)
apoc.math 45 Mathematical operations (sqrt, trig, statistics, etc.)
apoc.convert 24 Type conversion (toFloat, toJson, toList, etc.)
apoc.date 15 Date/time handling (format, parse, add, etc.)
apoc.json 18 JSON operations (parse, stringify, path, merge, etc.)
apoc.util 38 Utilities (md5, sha256, uuid, compress, etc.)
apoc.agg 15 Aggregation (median, percentile, stdev, histogram, etc.)
apoc.algo 9 Graph algorithms (pageRank, dijkstra, etc.)
apoc.map 25 Map operations (merge, flatten, groupBy, etc.)
apoc.create 19 Node/relationship creation (node, relationship, uuid, etc.)
apoc.export 14 Data export (json, csv, cypher, graphML, etc.)
apoc.import 19 Data import (json, csv, xml, etc.)
apoc.load 29 Data loading (json, csv, jdbc, s3, kafka, etc.)
apoc.log 25 Logging (info, debug, warn, metrics, etc.)
apoc.node 34 Node operations (degree, labels, properties, etc.)
apoc.nodes 22 Multi-node operations (group, partition, connected, etc.)
apoc.rel 29 Relationship operations (type, properties, weight, etc.)
apoc.refactor 20 Graph refactoring (mergeNodes, renameLabel, etc.)
apoc.schema 30 Schema operations (indexes, constraints, etc.)
apoc.meta 38 Metadata (schema, stats, types, etc.)
apoc.neighbors 6 Neighbor traversal (atHop, bfs, dfs, etc.)
apoc.path 9 Path operations (expand, slice, etc.)
apoc.paths 21 Path finding (shortest, all, kShortest, etc.)
apoc.periodic 10 Periodic operations (iterate, commit, etc.)
apoc.search 29 Search operations (fulltext, fuzzy, regex, etc.)
apoc.scoring 22 Similarity scoring (cosine, jaccard, bm25, etc.)
apoc.spatial 19 Spatial operations (distance, bearing, geohash, etc.)
apoc.stats 23 Statistics (mean, median, correlation, etc.)
apoc.temporal 26 Temporal operations (format, parse, duration, etc.)
apoc.trigger 24 Trigger management (add, remove, enable, etc.)
apoc.warmup 15 Cache warmup (run, nodes, relationships, etc.)
apoc.xml 23 XML operations (parse, query, transform, etc.)
apoc.label 27 Label operations (add, remove, exists, etc.)
apoc.lock 19 Locking (nodes, relationships, etc.)
apoc.merge 17 Merge operations (node, relationship, etc.)
apoc.hashing 18 Hashing (md5, sha256, murmur, etc.)
apoc.graph 15 Graph operations (fromData, validate, etc.)
apoc.diff 9 Diff operations (nodes, maps, etc.)
apoc.cypher 16 Cypher utilities (run, parallel, etc.)
apoc.bitwise 15 Bitwise operations (and, or, xor, etc.)
apoc.atomic 9 Atomic operations (add, update, etc.)
apoc.number 38 Number formatting (format, parse, toHex, etc.)

Creating Custom Plugins

Plugin Interface

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

// 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

# 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:

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:

# 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:

Image Plugins Location Functions
nornicdb-arm64-metal /app/plugins/apoc.so 964
nornicdb-amd64-cuda /app/plugins/apoc.so 964
nornicdb-amd64-cpu /app/plugins/apoc.so 964

Troubleshooting

Plugin Not Loading

  1. Check plugin file exists and is readable:

    ls -la /app/plugins/
    

  2. Verify Go version compatibility (plugins must be built with same Go version):

    go version
    

  3. Check logs for errors:

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

Function Not Found

  1. Check if function exists:

    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

Platform Plugin Support Notes
Linux (amd64) ✅ Full Native Go plugin support
Linux (arm64) ✅ Full Native Go plugin support
macOS (arm64) ✅ Full Native Go plugin support
macOS (amd64) ✅ Full Native Go plugin support
Windows ❌ None Go 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