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
.sofiles 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:
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¶
-
Check plugin file exists and is readable:
-
Verify Go version compatibility (plugins must be built with same Go version):
-
Check logs for errors:
Function Not Found¶
-
Check if function exists:
-
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