initial draft of neo4j database driver
This commit is contained in:
108
pkg/neo4j/schema.go
Normal file
108
pkg/neo4j/schema.go
Normal file
@@ -0,0 +1,108 @@
|
||||
package neo4j
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// applySchema creates Neo4j constraints and indexes for Nostr events
|
||||
// Neo4j uses Cypher queries to define schema constraints and indexes
|
||||
func (n *N) applySchema(ctx context.Context) error {
|
||||
n.Logger.Infof("applying Nostr schema to neo4j")
|
||||
|
||||
// Create constraints and indexes using Cypher queries
|
||||
// Constraints ensure uniqueness and are automatically indexed
|
||||
constraints := []string{
|
||||
// Unique constraint on Event.id (event ID must be unique)
|
||||
"CREATE CONSTRAINT event_id_unique IF NOT EXISTS FOR (e:Event) REQUIRE e.id IS UNIQUE",
|
||||
|
||||
// Unique constraint on Author.pubkey (author public key must be unique)
|
||||
"CREATE CONSTRAINT author_pubkey_unique IF NOT EXISTS FOR (a:Author) REQUIRE a.pubkey IS UNIQUE",
|
||||
|
||||
// Unique constraint on Marker.key (marker key must be unique)
|
||||
"CREATE CONSTRAINT marker_key_unique IF NOT EXISTS FOR (m:Marker) REQUIRE m.key IS UNIQUE",
|
||||
}
|
||||
|
||||
// Additional indexes for query optimization
|
||||
indexes := []string{
|
||||
// Index on Event.kind for kind-based queries
|
||||
"CREATE INDEX event_kind IF NOT EXISTS FOR (e:Event) ON (e.kind)",
|
||||
|
||||
// Index on Event.created_at for time-range queries
|
||||
"CREATE INDEX event_created_at IF NOT EXISTS FOR (e:Event) ON (e.created_at)",
|
||||
|
||||
// Index on Event.serial for serial-based lookups
|
||||
"CREATE INDEX event_serial IF NOT EXISTS FOR (e:Event) ON (e.serial)",
|
||||
|
||||
// Composite index for common query patterns (kind + created_at)
|
||||
"CREATE INDEX event_kind_created_at IF NOT EXISTS FOR (e:Event) ON (e.kind, e.created_at)",
|
||||
|
||||
// Index on Tag.type for tag-type queries
|
||||
"CREATE INDEX tag_type IF NOT EXISTS FOR (t:Tag) ON (t.type)",
|
||||
|
||||
// Index on Tag.value for tag-value queries
|
||||
"CREATE INDEX tag_value IF NOT EXISTS FOR (t:Tag) ON (t.value)",
|
||||
|
||||
// Composite index for tag queries (type + value)
|
||||
"CREATE INDEX tag_type_value IF NOT EXISTS FOR (t:Tag) ON (t.type, t.value)",
|
||||
}
|
||||
|
||||
// Execute all constraint creation queries
|
||||
for _, constraint := range constraints {
|
||||
if _, err := n.ExecuteWrite(ctx, constraint, nil); err != nil {
|
||||
return fmt.Errorf("failed to create constraint: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Execute all index creation queries
|
||||
for _, index := range indexes {
|
||||
if _, err := n.ExecuteWrite(ctx, index, nil); err != nil {
|
||||
return fmt.Errorf("failed to create index: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
n.Logger.Infof("schema applied successfully")
|
||||
return nil
|
||||
}
|
||||
|
||||
// dropAll drops all data from neo4j (useful for testing)
|
||||
func (n *N) dropAll(ctx context.Context) error {
|
||||
n.Logger.Warningf("dropping all data from neo4j")
|
||||
|
||||
// Delete all nodes and relationships
|
||||
_, err := n.ExecuteWrite(ctx, "MATCH (n) DETACH DELETE n", nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to drop all data: %w", err)
|
||||
}
|
||||
|
||||
// Drop all constraints
|
||||
constraints := []string{
|
||||
"DROP CONSTRAINT event_id_unique IF EXISTS",
|
||||
"DROP CONSTRAINT author_pubkey_unique IF EXISTS",
|
||||
"DROP CONSTRAINT marker_key_unique IF EXISTS",
|
||||
}
|
||||
|
||||
for _, constraint := range constraints {
|
||||
_, _ = n.ExecuteWrite(ctx, constraint, nil)
|
||||
// Ignore errors as constraints may not exist
|
||||
}
|
||||
|
||||
// Drop all indexes
|
||||
indexes := []string{
|
||||
"DROP INDEX event_kind IF EXISTS",
|
||||
"DROP INDEX event_created_at IF EXISTS",
|
||||
"DROP INDEX event_serial IF EXISTS",
|
||||
"DROP INDEX event_kind_created_at IF EXISTS",
|
||||
"DROP INDEX tag_type IF EXISTS",
|
||||
"DROP INDEX tag_value IF EXISTS",
|
||||
"DROP INDEX tag_type_value IF EXISTS",
|
||||
}
|
||||
|
||||
for _, index := range indexes {
|
||||
_, _ = n.ExecuteWrite(ctx, index, nil)
|
||||
// Ignore errors as indexes may not exist
|
||||
}
|
||||
|
||||
// Reapply schema after dropping
|
||||
return n.applySchema(ctx)
|
||||
}
|
||||
Reference in New Issue
Block a user