Skip to content

Commit

Permalink
docs: Add Dynamic Knowledge Graph cookbook
Browse files Browse the repository at this point in the history
  • Loading branch information
NeilJohnson0930 committed Jan 24, 2025
1 parent 9cceb01 commit f141136
Show file tree
Hide file tree
Showing 3 changed files with 971 additions and 368 deletions.
82 changes: 78 additions & 4 deletions camel/storages/graph_storages/neo4j_graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -339,18 +339,24 @@ def refresh_schema(self) -> None:
]
)

def add_triplet(self, subj: str, obj: str, rel: str) -> None:
r"""Adds a relationship (triplet) between two entities in the database.
def add_triplet(
self, subj: str, obj: str, rel: str, timestamp: Optional[str] = None
) -> None:
r"""Adds a relationship (triplet) between two entities
in the database with a timestamp.
Args:
subj (str): The identifier for the subject entity.
obj (str): The identifier for the object entity.
rel (str): The relationship between the subject and object.
timestamp (Optional[str]): The timestamp of the relationship.
Defaults to None.
"""
query = """
MERGE (n1:`%s` {id:$subj})
MERGE (n2:`%s` {id:$obj})
MERGE (n1)-[:`%s`]->(n2)
MERGE (n1)-[r:`%s`]->(n2)
SET r.timestamp = $timestamp
"""

prepared_statement = query % (
Expand All @@ -361,7 +367,10 @@ def add_triplet(self, subj: str, obj: str, rel: str) -> None:

# Execute the query within a database session
with self.driver.session(database=self.database) as session:
session.run(prepared_statement, {"subj": subj, "obj": obj})
session.run(
prepared_statement,
{"subj": subj, "obj": obj, "timestamp": timestamp},
)

def _delete_rel(self, subj: str, obj: str, rel: str) -> None:
r"""Deletes a specific relationship between two nodes in the Neo4j
Expand Down Expand Up @@ -721,3 +730,68 @@ def common_neighbour_aware_random_walk(
return result[0] if result else {}
except CypherSyntaxError as e:
raise ValueError(f"Generated Cypher Statement is not valid\n{e}")

def get_triplet(
self,
subj: Optional[str] = None,
obj: Optional[str] = None,
rel: Optional[str] = None,
) -> List[Dict[str, Any]]:
"""
Query triplet information. If subj, obj, or rel is
not specified, returns all matching triplets.
Args:
subj (Optional[str]): The ID of the subject node.
If None, matches any subject node.
obj (Optional[str]): The ID of the object node.
If None, matches any object node.
rel (Optional[str]): The type of relationship.
If None, matches any relationship type.
Returns:
List[Dict[str, Any]]: A list of matching triplets,
each containing subj, obj, rel, and timestamp.
"""
import logging

logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)

# Construct the query
query = """
MATCH (n1:Entity)-[r]->(n2:Entity)
WHERE ($subj IS NULL OR n1.id = $subj)
AND ($obj IS NULL OR n2.id = $obj)
AND ($rel IS NULL OR type(r) = $rel)
RETURN n1.id AS subj, n2.id AS obj,
type(r) AS rel, r.timestamp AS timestamp
"""

# Construct the query parameters
params = {
"subj": subj
if subj is not None
else None, # If subj is None, match any subject node
"obj": obj
if obj is not None
else None, # If obj is None, match any object node
"rel": rel
if rel is not None
else None, # If rel is None, match any relationship type
}

logger.debug(f"Executing query: {query}")
logger.debug(f"Query parameters: {params}")

with self.driver.session(database=self.database) as session:
try:
result = session.run(query, params)
records = [record.data() for record in result]
logger.debug(
f"Query returned {len(records)} records: {records}"
)
return records
except Exception as e:
logger.error(f"Error executing query: {e}")
return []
Loading

0 comments on commit f141136

Please sign in to comment.