api/modules/database/tools/neontology_tools.py
2025-11-14 14:47:19 +00:00

127 lines
5.4 KiB
Python

from dotenv import load_dotenv, find_dotenv
load_dotenv(find_dotenv())
import os
import modules.logger_tool as logger
log_name = 'api_modules_database_tools_neontology_tools'
log_dir = os.getenv("LOG_PATH", "/logs") # Default path as fallback
logging = logger.get_logger(
name=log_name,
log_level=os.getenv("LOG_LEVEL", "DEBUG"),
log_path=log_dir,
log_file=log_name,
runtime=True,
log_format='default'
)
from modules.database.tools.neontology.graphconnection import init_neontology, close_neontology
from modules.database.tools.neontology.basenode import BaseNode
from modules.database.tools.neontology.baserelationship import BaseRelationship
from pydantic import ValidationError
import os
import neo4j
# Initialize Neontology with the Neo4j database details
def init_neontology_connection(uri=None, user=None, password=None):
uri = uri or os.getenv("APP_BOLT_URL")
user = user or os.getenv("USER_NEO4J") # Add default value
password = password or os.getenv("PASSWORD_NEO4J")
if not all([uri, user, password]):
raise ValueError("Missing required Neo4j connection parameters")
try:
logging.info(f"Initializing Neontology with URI: {uri}")
init_neontology(
neo4j_uri=uri,
neo4j_username=user,
neo4j_password=password
)
logging.info(f"Neontology connection initialized with URI: {uri}, user: {user}")
except Exception as e:
raise ValueError(f"Failed to initialize Neontology connection: {str(e)}")
def close_neontology_connection():
logging.debug(f"Attempting to terminate Neontology connection")
close_neontology()
logging.info(f"Neontology connection terminated")
# Terminates the Neo4j connection
def close_neo4j_connection():
logging.debug(f"Attempting to terminate Neo4j connection")
neo4j.close()
logging.info(f"Neo4j connection terminated")
# Create a Neontology node in the Neo4j database
def create_or_merge_neontology_node(node: BaseNode, database: str = 'neo4j', operation: str = "merge"):
"""
Create or merge a Neontology node in the Neo4j database.
Args:
node (BaseNode): A Neontology node object.
operation (str): The operation to perform ('create' or 'merge'). Defaults to 'merge'.
"""
try:
logging.debug(f"Creating/merging node: {node.__class__.__name__} with label '{node.__primarylabel__}' in database '{database}'")
logging.debug(f"Node data: {node.to_dict()}")
if operation == "create":
result = node.create(database=database)
logging.debug(f"Create result: {result}")
elif operation == "merge":
result = node.merge(database=database)
logging.debug(f"Merge result: {result}")
else:
logging.error(f"Invalid operation: {operation}")
except Exception as e:
logging.error(f"Error in processing node: {e}")
raise # Re-raise to see the actual error
# Create or merge a Neontology node in the Neo4j database. If a ValidationError occurs
# due to a NaN value, replace it with a default value and retry.
def create_or_merge_neontology_node_with_default(driver, node: BaseNode, database: str = 'neo4j', operation: str = "merge", default_values: dict = {}):
"""
Create or merge a Neontology node in the Neo4j database. If a ValidationError occurs
due to a NaN value, replace it with a default value and retry.
Args:
node (BaseNode): A Neontology node object.
operation (str): The operation to perform ('create' or 'merge'). Defaults to 'merge'.
default_values (dict): A dictionary of default values for fields that might contain NaN.
"""
try:
# Attempt to create or merge the node
if operation == "create":
node.create(database=database)
else: # "merge" by default
node.merge(database=database)
except ValidationError as e:
# Handle ValidationError due to NaN value
for field, error in e.errors():
if field in default_values and 'type' in error and error['type'] == 'value_error.nan':
setattr(node, field, default_values[field])
logging.warning(f"Warning: Replacing NaN in {field} with default value '{default_values[field]}' and retrying.")
create_or_merge_neontology_node_with_default(driver, node, database, operation, default_values)
break
else:
# If the error is not due to a NaN value or field not in default_values, re-raise the error
logging.error(f"Error in processing node: {e}")
raise
except Exception as e:
logging.error(f"Error in processing node: {e}")
def create_or_merge_neontology_relationship(relationship: BaseRelationship, database: str = 'neo4j', operation: str = "merge"):
"""
Create or merge a Neontology relationship in the Neo4j database.
Args:
relationship (BaseRelationship): A Neontology relationship object.
operation (str): The operation to perform ('create' or 'merge'). Defaults to 'merge'.
"""
try:
if operation == "create":
relationship.create(database=database)
elif operation == "merge":
relationship.merge(database=database)
else:
logging.error(f"Invalid operation: {operation}")
except Exception as e:
logging.error(f"Error in processing relationship: {e}")