Files
opendan/src/knowledge/object/relation.py
T

105 lines
3.3 KiB
Python
Raw Normal View History

2023-09-13 17:55:27 +08:00
# define a relation store class
from .object_id import ObjectID
2023-09-14 16:03:56 +08:00
import sqlite3
from typing import List, Tuple, Optional
2023-09-14 16:03:56 +08:00
import logging
import os
from enum import Enum
class ObjectRelationType(Enum):
Parent = 1
2023-09-13 17:55:27 +08:00
class ObjectRelationStore:
def __init__(self, root_dir: str):
2023-09-14 16:03:56 +08:00
if not os.path.exists(root_dir):
os.makedirs(root_dir)
file = os.path.join(root_dir, "relation.db")
logging.info(f"will init object relation store, db={file}")
2023-09-14 16:03:56 +08:00
self.conn = sqlite3.connect(file)
self.cursor = self.conn.cursor()
self.cursor.execute(
"""
CREATE TABLE IF NOT EXISTS relations (
object_id TEXT,
assoc_id TEXT,
relation_type TEXT,
PRIMARY KEY (object_id, assoc_id, relation_type)
2023-09-14 16:03:56 +08:00
)
"""
)
2023-09-13 17:55:27 +08:00
def add_relation(
self,
object_id: ObjectID,
assoc_id: ObjectID,
relation_type: ObjectRelationType = ObjectRelationType.Parent,
):
if relation_type == None:
relation_type = ObjectRelationType.Parent
2023-09-14 16:03:56 +08:00
self.cursor.execute(
"""
INSERT OR IGNORE INTO relations (object_id, assoc_id, relation_type)
VALUES (?, ?, ?)
2023-09-14 16:03:56 +08:00
""",
(str(object_id), str(assoc_id), relation_type.value),
2023-09-14 16:03:56 +08:00
)
self.conn.commit()
2023-09-13 17:55:27 +08:00
def get_related_objects(
self, object_id: ObjectID, relation_type: Optional[ObjectRelationType] = None
) -> List[ObjectID]:
if relation_type:
2023-09-14 16:03:56 +08:00
self.cursor.execute(
"""
SELECT assoc_id FROM relations WHERE object_id = ? AND relation_type = ?
2023-09-14 16:03:56 +08:00
""",
(str(object_id), relation_type.value),
2023-09-14 16:03:56 +08:00
)
else:
self.cursor.execute(
"""
SELECT assoc_id FROM relations WHERE object_id = ?
""",
(str(object_id),),
)
return [ObjectID.from_base58(row[0]) for row in self.cursor.fetchall()]
2023-09-13 17:55:27 +08:00
def get_related_root_objects(
self, object_id: ObjectID, relation_type: Optional[ObjectRelationType] = None
) -> List[ObjectID]:
root_objects = []
related_objects = self.get_related_objects(object_id, relation_type)
history = []
history.append(object_id)
while related_objects:
for obj in related_objects:
next_related_objects = self.get_related_objects(obj, relation_type)
if not next_related_objects:
if obj not in root_objects:
root_objects.append(obj)
else:
for related_object in next_related_objects:
if obj not in history:
related_objects.append(related_object)
else:
logging.warning(
f"loop detected: {obj} <-> {related_object}"
)
related_objects = next_related_objects
return root_objects
def delete_relation(self, object_id: ObjectID):
2023-09-14 16:03:56 +08:00
self.cursor.execute(
"""
DELETE FROM relations WHERE object_id = ?
2023-09-14 16:03:56 +08:00
""",
(str(object_id),),
)
self.conn.commit()