199 lines
8.6 KiB
Python
199 lines
8.6 KiB
Python
import os
|
|
from typing import Dict, Any
|
|
from modules.logger_tool import initialise_logger
|
|
import modules.database.tools.neo4j_driver_tools as driver_tools
|
|
import modules.database.tools.neo4j_session_tools as session_tools
|
|
|
|
class Neo4jService:
|
|
"""Service for managing Neo4j database operations"""
|
|
|
|
def __init__(self):
|
|
self.logger = initialise_logger(__name__, os.getenv("LOG_LEVEL"), os.getenv("LOG_PATH"), 'default', True)
|
|
self.driver = driver_tools.get_driver()
|
|
|
|
def check_database_exists(self, database_name: str) -> Dict[str, Any]:
|
|
"""Check if a Neo4j database exists
|
|
|
|
Args:
|
|
database_name (str): Name of the database to check
|
|
|
|
Returns:
|
|
Dict[str, Any]: Result containing existence status and operation status
|
|
"""
|
|
try:
|
|
with self.driver.session() as session:
|
|
result = session.run(
|
|
"SHOW DATABASES YIELD name WHERE name = $name",
|
|
name=database_name
|
|
)
|
|
exists = bool(result.single())
|
|
return {
|
|
"exists": exists,
|
|
"status": "success"
|
|
}
|
|
except Exception as e:
|
|
self.logger.error(f"Error checking database {database_name}: {str(e)}")
|
|
return {
|
|
"exists": False,
|
|
"status": "error",
|
|
"message": str(e)
|
|
}
|
|
|
|
def create_database(self, db_name: str) -> Dict[str, Any]:
|
|
"""Creates a Neo4j database with the given name
|
|
|
|
Args:
|
|
db_name (str): Name of the database to create
|
|
|
|
Returns:
|
|
Dict[str, Any]: Result containing operation status and message
|
|
"""
|
|
try:
|
|
# First check if database exists
|
|
exists_result = self.check_database_exists(db_name)
|
|
if exists_result["status"] == "error":
|
|
return exists_result
|
|
|
|
if not exists_result["exists"]:
|
|
with self.driver.session() as session:
|
|
session_tools.create_database(session, db_name)
|
|
self.logger.info(f"Created database {db_name}")
|
|
return {
|
|
"status": "success",
|
|
"message": f"Database {db_name} created successfully"
|
|
}
|
|
else:
|
|
self.logger.info(f"Database {db_name} already exists")
|
|
return {
|
|
"status": "success",
|
|
"message": f"Database {db_name} already exists"
|
|
}
|
|
|
|
except Exception as e:
|
|
self.logger.error(f"Error creating database {db_name}: {str(e)}")
|
|
return {"status": "error", "message": str(e)}
|
|
|
|
def initialize_schema(self, database_name: str) -> Dict[str, Any]:
|
|
"""Initialize Neo4j schema (constraints and indexes) for a database
|
|
|
|
Args:
|
|
database_name (str): Name of the database to initialize schema for
|
|
|
|
Returns:
|
|
Dict[str, Any]: Result containing operation status and message
|
|
"""
|
|
try:
|
|
with self.driver.session(database=database_name) as session:
|
|
# Create constraints
|
|
constraints = [
|
|
"CREATE CONSTRAINT IF NOT EXISTS FOR (n:School) REQUIRE n.unique_id IS UNIQUE",
|
|
"CREATE CONSTRAINT IF NOT EXISTS FOR (n:Department) REQUIRE n.unique_id IS UNIQUE",
|
|
"CREATE CONSTRAINT IF NOT EXISTS FOR (n:Subject) REQUIRE n.unique_id IS UNIQUE",
|
|
"CREATE CONSTRAINT IF NOT EXISTS FOR (n:YearGroup) REQUIRE n.unique_id IS UNIQUE",
|
|
"CREATE CONSTRAINT IF NOT EXISTS FOR (n:Class) REQUIRE n.unique_id IS UNIQUE",
|
|
"CREATE CONSTRAINT IF NOT EXISTS FOR (n:Teacher) REQUIRE n.unique_id IS UNIQUE",
|
|
"CREATE CONSTRAINT IF NOT EXISTS FOR (n:Student) REQUIRE n.unique_id IS UNIQUE",
|
|
"CREATE CONSTRAINT IF NOT EXISTS FOR (n:Calendar) REQUIRE n.unique_id IS UNIQUE",
|
|
"CREATE CONSTRAINT IF NOT EXISTS FOR (n:Term) REQUIRE n.unique_id IS UNIQUE",
|
|
"CREATE CONSTRAINT IF NOT EXISTS FOR (n:Week) REQUIRE n.unique_id IS UNIQUE",
|
|
"CREATE CONSTRAINT IF NOT EXISTS FOR (n:Day) REQUIRE n.unique_id IS UNIQUE",
|
|
"CREATE CONSTRAINT IF NOT EXISTS FOR (n:Period) REQUIRE n.unique_id IS UNIQUE"
|
|
]
|
|
|
|
# Create indexes
|
|
indexes = [
|
|
"CREATE INDEX IF NOT EXISTS FOR (n:School) ON (n.urn)",
|
|
"CREATE INDEX IF NOT EXISTS FOR (n:Department) ON (n.department_name)",
|
|
"CREATE INDEX IF NOT EXISTS FOR (n:Subject) ON (n.subject_name)",
|
|
"CREATE INDEX IF NOT EXISTS FOR (n:YearGroup) ON (n.year_group)",
|
|
"CREATE INDEX IF NOT EXISTS FOR (n:Class) ON (n.class_name)",
|
|
"CREATE INDEX IF NOT EXISTS FOR (n:Teacher) ON (n.email)",
|
|
"CREATE INDEX IF NOT EXISTS FOR (n:Student) ON (n.email)",
|
|
"CREATE INDEX IF NOT EXISTS FOR (n:Calendar) ON (n.calendar_name)",
|
|
"CREATE INDEX IF NOT EXISTS FOR (n:Term) ON (n.term_name)",
|
|
"CREATE INDEX IF NOT EXISTS FOR (n:Week) ON (n.week_number)",
|
|
"CREATE INDEX IF NOT EXISTS FOR (n:Day) ON (n.date)",
|
|
"CREATE INDEX IF NOT EXISTS FOR (n:Period) ON (n.period_name)"
|
|
]
|
|
|
|
# Execute all constraints
|
|
for constraint in constraints:
|
|
session.run(constraint)
|
|
|
|
# Execute all indexes
|
|
for index in indexes:
|
|
session.run(index)
|
|
|
|
self.logger.info(f"Successfully initialized schema for database {database_name}")
|
|
return {
|
|
"status": "success",
|
|
"message": f"Schema initialized successfully for database {database_name}"
|
|
}
|
|
|
|
except Exception as e:
|
|
self.logger.error(f"Error initializing schema for database {database_name}: {str(e)}")
|
|
return {
|
|
"status": "error",
|
|
"message": str(e)
|
|
}
|
|
|
|
def delete_database(self, db_name: str) -> Dict[str, Any]:
|
|
"""Deletes a Neo4j database
|
|
|
|
Args:
|
|
db_name (str): Name of the database to delete
|
|
|
|
Returns:
|
|
Dict[str, Any]: Result containing operation status and message
|
|
"""
|
|
try:
|
|
exists_result = self.check_database_exists(db_name)
|
|
if exists_result["status"] == "error":
|
|
return exists_result
|
|
|
|
if exists_result["exists"]:
|
|
with self.driver.session() as session:
|
|
session_tools.reset_database_in_session(session)
|
|
self.logger.info(f"Deleted database {db_name}")
|
|
return {
|
|
"status": "success",
|
|
"message": f"Database {db_name} deleted successfully"
|
|
}
|
|
else:
|
|
return {
|
|
"status": "success",
|
|
"message": f"Database {db_name} does not exist"
|
|
}
|
|
|
|
except Exception as e:
|
|
self.logger.error(f"Error deleting database {db_name}: {str(e)}")
|
|
return {"status": "error", "message": str(e)}
|
|
|
|
def check_node_exists(self, database_name: str, node_label: str) -> Dict[str, Any]:
|
|
"""Check if any nodes with the given label exist in the specified database
|
|
|
|
Args:
|
|
database_name (str): Name of the database to check
|
|
node_label (str): Label of the node type to check for
|
|
|
|
Returns:
|
|
Dict[str, Any]: Result containing count and operation status
|
|
"""
|
|
try:
|
|
with self.driver.session(database=database_name) as session:
|
|
nodes = session_tools.find_nodes_by_label(session, node_label)
|
|
count = len(nodes)
|
|
return {
|
|
"exists": count > 0,
|
|
"count": count,
|
|
"status": "success"
|
|
}
|
|
except Exception as e:
|
|
self.logger.error(f"Error checking for {node_label} nodes in database {database_name}: {str(e)}")
|
|
return {
|
|
"exists": False,
|
|
"count": 0,
|
|
"status": "error",
|
|
"message": str(e)
|
|
}
|