diff --git a/app/frontend/ui_graph_service.py b/app/frontend/ui_graph_service.py index 763cc1f..5287b2a 100644 --- a/app/frontend/ui_graph_service.py +++ b/app/frontend/ui_graph_service.py @@ -211,9 +211,13 @@ class GraphExplorerService: if note and note.get("title"): note_titles_to_search.append(note.get("title")) - # Für jeden Titel: Suche nach exaktem Match + # Für jeden Titel: Suche nach exaktem Match UND nach "Titel#*" Varianten + # Da Qdrant keine Wildcard-Suche hat, müssen wir explizit nach bekannten Varianten suchen + # ABER: Wir wissen nicht, welche Abschnitte existieren, also müssen wir alle möglichen target_ids prüfen for title in note_titles_to_search: + # Exakte Übereinstimmung shoulds.append(models.FieldCondition(key="target_id", match=models.MatchValue(value=title))) + # WICHTIG: "Titel#Abschnitt" Varianten werden in Case D gefunden (clientseitige Filterung) if shoulds: in_filter = models.Filter( @@ -225,19 +229,23 @@ class GraphExplorerService: results.extend(res_in) # Case D: ZUSÄTZLICHE Suche für "Titel#Abschnitt" Format (nur für INCOMING edges) + # PROBLEM: Wikilinks wie [[Titel#Abschnitt]] werden als target_id="Titel#Abschnitt" gespeichert # Da Qdrant keine Wildcard-Suche hat, müssen wir breiter suchen und clientseitig filtern # WICHTIG: Diese Suche ist nur für eingehende Kanten relevant # Für ausgehende Kanten werden alle über note_id gefunden, unabhängig vom target_id Format if note_titles_to_search: # Erweiterte Suche: Lade alle relevanten Kanten und filtere clientseitig # Dies ist notwendig, weil "Titel#Abschnitt" nicht exakt mit "Titel" übereinstimmt - # OPTIMIERUNG: Nur wenn wir Titel haben, und mit begrenztem Limit + # STRATEGIE: Lade alle Kanten (ohne target_id Filter) und filtere clientseitig + # nach target_ids, die mit "Titel#" beginnen + extended_filter = models.Filter( must=[models.FieldCondition(key="kind", match=models.MatchExcept(**{"except": SYSTEM_EDGES}))] ) - # Lade Kanten für die clientseitige Filterung (Limit basierend auf Anzahl der Titel) - # Für jeden Titel könnten mehrere "Titel#Abschnitt" Varianten existieren - res_extended, _ = self.client.scroll(self.edges_col, scroll_filter=extended_filter, limit=2000, with_payload=True) + # Lade Kanten für die clientseitige Filterung + # Limit erhöht, um auch seltene "Titel#Abschnitt" Varianten zu finden + # WICHTIG: Dies ist notwendig, da wir nicht wissen, welche Abschnitte existieren + res_extended, _ = self.client.scroll(self.edges_col, scroll_filter=extended_filter, limit=5000, with_payload=True) # Clientseitige Filterung: Finde Kanten, deren target_id mit einem unserer Titel beginnt # Erstelle Set der bereits gefundenen Edge-IDs für schnelle Deduplizierung @@ -247,7 +255,10 @@ class GraphExplorerService: tgt_id = edge.payload.get("target_id", "") if tgt_id and edge.id not in existing_edge_ids: # Prüfe, ob target_id mit einem unserer Titel beginnt (für "Titel#Abschnitt" Format) + # ODER exakt dem Titel entspricht for title in note_titles_to_search: + # Exakte Übereinstimmung oder beginnt mit "Titel#" + # WICHTIG: startswith prüft auch exakte Übereinstimmung (title == tgt_id) if tgt_id.startswith(title + "#") or tgt_id == title: results.append(edge) existing_edge_ids.add(edge.id)