Files
natureinpots_community/app/neo4j_utils.py
2025-06-04 23:24:16 -05:00

104 lines
4.2 KiB
Python
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# app/neo4j_utils.py
from neo4j import GraphDatabase
from flask import current_app
class Neo4jHandler:
def __init__(self, uri=None, user=None, password=None):
# We read from current_app.config if nothing is passed in explicitly.
# If you already set NEO4J_URI / NEO4J_USER / NEO4J_PASSWORD in your config.py,
# these defaults will be overridden by those values automatically.
uri = uri or current_app.config.get("NEO4J_URI", "bolt://nip_neo4j:7687")
user = user or current_app.config.get("NEO4J_USER", "neo4j")
pw = password or current_app.config.get("NEO4J_PASSWORD", "your_password_here")
self.driver = GraphDatabase.driver(uri, auth=(user, pw))
def close(self):
self.driver.close()
def create_plant_node(self, uuid: str, name: str = "Unknown"):
"""
MERGE a Plant node by UUID. On create, set its name.
We strip() and strip('"') in case the CSV had extra quotes or spaces around the UUID.
"""
if not uuid:
print("[⚠️] Skipped node creation: missing UUID")
return
# Remove surrounding quotes or whitespace
uuid_clean = uuid.strip().strip('"')
name_clean = (name or "Unknown").strip()
print(f"[] (Neo4j) MERGE Plant node → uuid='{uuid_clean}', name='{name_clean}'")
try:
with self.driver.session() as session:
session.run(
"""
MERGE (p:Plant {uuid: $uuid})
ON CREATE SET p.name = $name
""",
uuid=uuid_clean,
name=name_clean
)
except Exception as e:
print(f"[❌] Neo4j node creation failed for UUID={uuid_clean}: {e}")
def create_lineage(self, child_uuid: str, parent_uuid: str):
"""
MATCH both child and parent by UUID, then MERGE a LINEAGE relationship.
Again, strip() any extraneous quotes or whitespace.
"""
if not child_uuid or not parent_uuid:
print(f"[⚠️] Skipped lineage creation: missing UUID(s) ({child_uuid!r}{parent_uuid!r})")
return
child_clean = child_uuid.strip().strip('"')
parent_clean = parent_uuid.strip().strip('"')
print(f"[] (Neo4j) Attempting to MERGE LINEAGE → child='{child_clean}', parent='{parent_clean}'")
try:
with self.driver.session() as session:
result = session.run(
"""
MATCH (c:Plant {uuid: $child_uuid})
MATCH (p:Plant {uuid: $parent_uuid})
MERGE (c)-[r:LINEAGE]->(p)
RETURN type(r) AS rel_type
""",
child_uuid=child_clean,
parent_uuid=parent_clean
)
record = result.single()
if record and record.get("rel_type") == "LINEAGE":
print(f"[✅] (Neo4j) Created LINEAGE → {child_clean}{parent_clean}")
else:
print(f"[⚠️] (Neo4j) No LINEAGE created (nodes may not match) → {child_clean}{parent_clean}")
except Exception as e:
print(f"[❌] Neo4j lineage creation failed: {e}")
def debug_check_node(self, uuid: str):
"""
Utility: check whether a Plant node with this UUID exists in Neo4j.
"""
uuid_clean = uuid.strip().strip('"')
with self.driver.session() as session:
result = session.run(
"MATCH (p:Plant {uuid: $uuid}) RETURN p",
uuid=uuid_clean
)
record = result.single()
if record:
print(f"[✅] (Neo4j) Node '{uuid_clean}' exists.")
else:
print(f"[❌] (Neo4j) Node '{uuid_clean}' NOT found.")
def get_neo4j_handler() -> Neo4jHandler:
"""
Factory: read NEO4J_URI / NEO4J_USER / NEO4J_PASSWORD from current_app.config.
"""
uri = current_app.config.get("NEO4J_URI", "bolt://nip_neo4j:7687")
user = current_app.config.get("NEO4J_USER", "neo4j")
password = current_app.config.get("NEO4J_PASSWORD", "your_password_here")
return Neo4jHandler(uri, user, password)