Skip to content

Commit 6b0be57

Browse files
committed
Optimization: SqlImplementation.relationships_metadata()
- Add: SqlImplementation._axiom_annotations_all() - Update: SqlImplementation.relationships_metadata(): Increased performance to O(log n) - Update: Added docstrings for several related methods
1 parent aab87c5 commit 6b0be57

File tree

1 file changed

+60
-2
lines changed

1 file changed

+60
-2
lines changed

src/oaklib/implementations/sqldb/sql_implementation.py

Lines changed: 60 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1065,8 +1065,60 @@ def _rbox_relationships(
10651065
def relationships_metadata(
10661066
self, relationships: Iterable[RELATIONSHIP], **kwargs
10671067
) -> Iterator[Tuple[RELATIONSHIP, List[Tuple[PRED_CURIE, Any]]]]:
1068-
for rel in relationships:
1069-
anns = [(ann.predicate, ann.object) for ann in self._axiom_annotations(*rel)]
1068+
"""For given relationships, returns axiom annotation metadata"""
1069+
# Fetch all annotations
1070+
anns: List[om.Annotation] = self._axiom_annotations_all()
1071+
# Simplify objects
1072+
anns: List[Dict[str, str]] = [{
1073+
'subject': x.subject,
1074+
'object': x.object,
1075+
'predicate': x.predicate,
1076+
'annotation_predicate': x.annotation_predicate,
1077+
'annotation_value_or_obj': x.annotation_value if x.annotation_value is not None else x.annotation_object,
1078+
} for x in anns]
1079+
# Create lookup for annotations based using edges as keys
1080+
rel_anns: Dict[RELATIONSHIP, List[Tuple[PRED_CURIE, Any]]] = {}
1081+
for x in anns:
1082+
key = (x['subject'], x['predicate'], x['object'])
1083+
if key not in rel_anns:
1084+
rel_anns[key] = []
1085+
rel_anns[key].append((x['annotation_predicate'], x['annotation_value_or_obj']))
1086+
# Group annotations by relationship, and yield
1087+
rel_anns = {rel: rel_anns[rel] if rel in rel_anns else [] for rel in relationships}
1088+
for rel, anns in rel_anns.items():
1089+
yield rel, anns
1090+
1091+
def relationships_metadata2(
1092+
self, relationships: Iterable[RELATIONSHIP], **kwargs
1093+
) -> Iterator[Tuple[RELATIONSHIP, List[Tuple[PRED_CURIE, Any]]]]:
1094+
"""For given relationships, returns axiom annotation metadata"""
1095+
# Split based on predicate
1096+
preds: Set[PRED_CURIE] = {x[1] for x in relationships}
1097+
rel_anns_all = {}
1098+
for pred in preds:
1099+
# Filter rels
1100+
rels = [x for x in relationships if x[1] == pred]
1101+
# Fetch annotations for given relationships
1102+
subs, objs = [x[0] for x in rels], [x[2] for x in rels]
1103+
anns: List[om.Annotation] = [x for x in self._axiom_annotations_multi(subs, pred, objs)]
1104+
anns: List[Dict[str, str]] = [{
1105+
'subject': row.subject,
1106+
'object': row.object,
1107+
'predicate': row.predicate,
1108+
'annotation_predicate': row.annotation_predicate,
1109+
'annotation_value_or_obj': row.annotation_value if row.annotation_value is not None else row.annotation_object,
1110+
} for row in anns]
1111+
rel_anns: Dict[RELATIONSHIP, List[Tuple[PRED_CURIE, Any]]] = {}
1112+
for x in anns:
1113+
key = (x['subject'], x['predicate'], x['object'])
1114+
if key not in rel_anns:
1115+
rel_anns[key] = []
1116+
rel_anns[key].append((x['annotation_predicate'], x['annotation_value_or_obj']))
1117+
# Group annotations by relationship
1118+
rel_anns = {rel: rel_anns[rel] if rel in rel_anns else [] for rel in rels}
1119+
rel_anns_all.update(rel_anns)
1120+
# Yield
1121+
for rel, anns in rel_anns_all.items():
10701122
yield rel, anns
10711123

10721124
def node_exists(self, curie: CURIE) -> bool:
@@ -1374,6 +1426,7 @@ def synonym_property_values(
13741426
def _axiom_annotations(
13751427
self, subject: CURIE, predicate: CURIE, object: CURIE = None, value: Any = None
13761428
) -> List[om.Annotation]:
1429+
"""Get all axiom annotations for a single edge."""
13771430
q = self.session.query(OwlAxiomAnnotation)
13781431
q = q.filter(OwlAxiomAnnotation.subject == subject)
13791432
q = q.filter(OwlAxiomAnnotation.predicate == predicate)
@@ -1396,6 +1449,7 @@ def _axiom_annotations_multi(
13961449
objects: List[CURIE] = None,
13971450
values: List[Any] = None,
13981451
) -> Iterator[OwlAxiomAnnotation]:
1452+
"""Get all axiom annotations from multiple edges sharing the same predicate."""
13991453
q = self.session.query(OwlAxiomAnnotation)
14001454
if subjects:
14011455
q = q.filter(OwlAxiomAnnotation.subject.in_(subjects))
@@ -1407,6 +1461,10 @@ def _axiom_annotations_multi(
14071461
for row in q:
14081462
yield row
14091463

1464+
def _axiom_annotations_all(self) -> List[OwlAxiomAnnotation]:
1465+
"""Get all axiom annotations."""
1466+
return self.session.query(OwlAxiomAnnotation).all()
1467+
14101468
def ancestors(
14111469
self,
14121470
start_curies: Union[CURIE, List[CURIE]],

0 commit comments

Comments
 (0)