Indexes and constraints
Creating, dropping, and querying indexes and constraints in gr.
Indexes
Indexes speed up MATCH patterns that filter on a property.
Without an index, gr scans every node with the given label.
With an index, it narrows the search in O(log n).
Property index
CREATE INDEX FOR (n:Person) ON (n.name)
gr creates a range index that supports equality (= "Alice"), range (> 25, < 30), prefix (STARTS WITH "A"), and IN [...] predicates.
Named index
CREATE INDEX idx_person_name FOR (n:Person) ON (n.name)
Providing a name makes the index easier to reference in DROP INDEX and SHOW INDEXES.
Composite index
CREATE INDEX FOR (n:Person) ON (n.name, n.age)
A composite index covers queries that filter on both columns together, or on the leading column alone.
Relationship property index
CREATE INDEX FOR ()-[r:KNOWS]-() ON (r.since)
Indexes relationship properties the same way as node properties.
Drop an index
DROP INDEX idx_person_name
DROP INDEX IF EXISTS idx_person_name
Show indexes
SHOW INDEXES
Returns: name, type, labelsOrTypes, properties, state (ONLINE or POPULATING).
Indexes and MERGE
MERGE on an indexed property does a single index look-up instead of a full scan.
Always create an index before running MERGE on a property that could match many nodes.
Constraints
Constraints enforce invariants at write time.
A write that violates a constraint returns *engine.ConstraintError and the transaction rolls back.
Uniqueness constraint
CREATE CONSTRAINT FOR (n:Person) REQUIRE n.email IS UNIQUE
Every Person node must have a distinct email value.
Two Persons without an email property are allowed (nulls are not compared for uniqueness).
gr automatically creates a supporting index for the constrained property.
Node key constraint
A node key combines uniqueness and existence:
CREATE CONSTRAINT FOR (n:Person) REQUIRE (n.id) IS NODE KEY
Every Person node must have an id property, and no two Person nodes can share the same id.
Composite node key:
CREATE CONSTRAINT FOR (n:Person) REQUIRE (n.firstName, n.lastName) IS NODE KEY
Property existence constraint
CREATE CONSTRAINT FOR (n:Person) REQUIRE n.name IS NOT NULL
Every Person node must have a name property.
Relationship property existence
CREATE CONSTRAINT FOR ()-[r:KNOWS]-() REQUIRE r.since IS NOT NULL
Every KNOWS relationship must have a since property.
Named constraint
CREATE CONSTRAINT person_email_unique FOR (n:Person) REQUIRE n.email IS UNIQUE
Drop a constraint
DROP CONSTRAINT person_email_unique
DROP CONSTRAINT IF EXISTS person_email_unique
Show constraints
SHOW CONSTRAINTS
Returns: name, type, labelsOrTypes, properties.
Handling constraint errors in Go
import (
"errors"
"github.com/tamnd/gr/engine"
)
_, err = db.Exec(ctx, `CREATE (:Person {email:"a@b.com"})`, nil)
var ce *engine.ConstraintError
if errors.As(err, &ce) {
fmt.Printf("constraint %q violated: %v\n", ce.Constraint, ce.Message)
}
Schema catalog
List all labels, relationship types, and property keys:
SHOW LABELS
SHOW RELATIONSHIP TYPES
SHOW PROPERTY KEYS
From the CLI:
gr run graph.gr "SHOW INDEXES"
gr run graph.gr "SHOW CONSTRAINTS"
gr run graph.gr "SHOW LABELS"
Inside the shell:
gr> :schema