Schema management¶
Neo4j allows a flexible schema management, where you can define indexes and constraints on the properties of nodes and relationships. To learn more, please refer to the Neo4j schema documentation.
Defining your model¶
neomodel allows you to define indexes and constraints in your node and relationship classes, like so:
from neomodel import (StructuredNode, StructuredRel, StringProperty,
IntegerProperty, RelationshipTo)
class LocatedIn(StructuredRel):
since = IntegerProperty(index=True)
class Country(StructuredNode):
code = StringProperty(unique_index=True)
class City(StructuredNode):
name = StringProperty(index=True)
country = RelationshipTo(Country, 'FROM_COUNTRY', model=LocatedIn)
Applying constraints and indexes¶
After creating your model, any constraints or indexes must be applied to Neo4j and neomodel
provides a
script (neomodel_install_labels) to automate this:
$ neomodel_install_labels yourapp.py someapp.models --db bolt://neo4j_username:neo4j_password@localhost:7687
It is important to execute this after altering the schema and observe the number of classes it reports.
Ommitting the --db
argument will default to the NEO4J_BOLT_URL
environment variable. This is useful for masking
your credentials.
Note
The script will only create indexes and constraints that are defined in your model classes. It will not remove any existing indexes or constraints that are not defined in your model classes.
Indexes¶
The following indexes are supported:
index=True
: This will create the default Neo4j index on the property (currently RANGE).fulltext_index=FulltextIndex()
: This will create a FULLTEXT index on the property. Only available for Neo4j version 5.16 or higher. With this one, you can define the following options:analyzer
: The analyzer to use. The default isstandard-no-stop-words
.eventually_consistent
: Whether the index should be eventually consistent. The default isFalse
.
Please refer to the Neo4j documentation. for more information on fulltext indexes.
vector_index=VectorIndex()
: This will create a VECTOR index on the property. Only available for Neo4j version 5.15 (node) and 5.18 (relationship) or higher. With this one, you can define the following options:dimensions
: The dimension of the vector. The default is 1536.similarity_function
: The similarity algorithm to use. The default iscosine
.
Those indexes are available for both node- and relationship properties.
Note
Yes, you can create multiple indexes of a different type on the same property. For example, a default index and a fulltext index.
Note
For the semantic indexes (fulltext and vector), this allows you to create indexes, but searching those indexes require using Cypher queries. This is because Cypher only supports querying those indexes through a specific procedure for now.
Full example:
from neomodel import StructuredNode, StringProperty, FulltextIndex, VectorIndex
class VeryIndexedNode(StructuredNode):
name = StringProperty(
index=True,
fulltext_index=FulltextIndex(analyzer='english', eventually_consistent=True)
)
name_embedding = ArrayProperty(
FloatProperty(),
vector_index=VectorIndex(dimensions=512, similarity_function='euclidean')
)
Constraints¶
The following constraints are supported:
unique_index=True
: This will create a uniqueness constraint on the property. Available for both nodes and relationships (Neo4j version 5.7 or higher).
Note
The uniqueness constraint of Neo4j is not supported as such, but using required=True
on a property serves the same purpose.
Extracting the schema from a database¶
You can extract the schema from an existing database using the neomodel_inspect_database
script (Database Inspection - Requires APOC).
This script will output the schema in the neomodel format, including indexes and constraints.