ausgehende Kanten

This commit is contained in:
Lars 2025-12-14 14:50:06 +01:00
parent f7a4dab707
commit f313f0873b
2 changed files with 27 additions and 22 deletions

View File

@ -14,6 +14,7 @@ def render_graph_explorer(graph_service):
# Defaults für View & Physik setzen
st.session_state.setdefault("graph_depth", 2)
st.session_state.setdefault("graph_show_labels", True)
# Höhere Default-Werte für Abstand
st.session_state.setdefault("graph_spacing", 250)
st.session_state.setdefault("graph_gravity", -4000)
@ -78,7 +79,7 @@ def render_graph_explorer(graph_service):
show_labels=st.session_state.graph_show_labels
)
# WICHTIG: Volle Daten inkl. Stitching für Editor holen
# WICHTIG: Daten für Editor holen (inkl. Pfad)
note_data = graph_service.get_note_with_full_content(center_id)
# Action Bar rendern
@ -122,7 +123,7 @@ def render_graph_explorer(graph_service):
"solver": "barnesHut",
"barnesHut": {
"gravitationalConstant": st.session_state.graph_gravity,
"centralGravity": 0.005,
"centralGravity": 0.005, # Extrem wichtig für die Ausbreitung!
"springLength": st.session_state.graph_spacing,
"springConstant": 0.04,
"damping": 0.09,

View File

@ -154,49 +154,53 @@ class GraphExplorerService:
return previews
def _find_connected_edges(self, note_ids, note_title=None):
"""Findet eingehende und ausgehende Kanten für Nodes."""
"""Findet eingehende und ausgehende Kanten."""
results = []
# 1. Chunk IDs ermitteln (da Edges oft an Chunks hängen)
# 1. OUTGOING EDGES (Der "Owner"-Fix)
# Wir suchen Kanten, die im Feld 'note_id' (Owner) eine unserer Notizen haben.
# Das findet ALLE ausgehenden Kanten, egal ob sie an einem Chunk oder der Note hängen.
if note_ids:
out_filter = models.Filter(must=[
models.FieldCondition(key="note_id", match=models.MatchAny(any=note_ids)),
models.FieldCondition(key="kind", match=models.MatchExcept(**{"except": SYSTEM_EDGES}))
])
# Limit hoch, um alles zu finden
res_out, _ = self.client.scroll(self.edges_col, scroll_filter=out_filter, limit=500, with_payload=True)
results.extend(res_out)
# 2. INCOMING EDGES (Ziel = Chunk ID oder Titel oder Note ID)
# Hier müssen wir Chunks auflösen, um Treffer auf Chunks zu finden.
# Chunk IDs der aktuellen Notes holen
chunk_ids = []
if note_ids:
c_filter = models.Filter(must=[models.FieldCondition(key="note_id", match=models.MatchAny(any=note_ids))])
chunks, _ = self.client.scroll(self.chunks_col, scroll_filter=c_filter, limit=300)
chunk_ids = [c.id for c in chunks]
# 2. Outgoing Edges suchen
# Source kann sein: Eine Chunk ID ODER die Note ID selbst (bei direkten Links)
source_candidates = chunk_ids + note_ids
if source_candidates:
out_f = models.Filter(must=[
models.FieldCondition(key="source_id", match=models.MatchAny(any=source_candidates)),
# FIX: MatchExcept Workaround für Pydantic
models.FieldCondition(key="kind", match=models.MatchExcept(**{"except": SYSTEM_EDGES}))
])
res_out, _ = self.client.scroll(self.edges_col, scroll_filter=out_f, limit=500, with_payload=True)
results.extend(res_out)
# 3. Incoming Edges suchen
# Target kann sein: Chunk ID, Note ID, oder Note Titel (Wikilinks)
shoulds = []
# Case A: Edge zeigt auf einen unserer Chunks
if chunk_ids:
shoulds.append(models.FieldCondition(key="target_id", match=models.MatchAny(any=chunk_ids)))
# Case B: Edge zeigt direkt auf unsere Note ID
if note_ids:
shoulds.append(models.FieldCondition(key="target_id", match=models.MatchAny(any=note_ids)))
# Case C: Edge zeigt auf unseren Titel (Wikilinks)
if note_title:
shoulds.append(models.FieldCondition(key="target_id", match=models.MatchValue(value=note_title)))
if shoulds:
in_f = models.Filter(
in_filter = models.Filter(
must=[models.FieldCondition(key="kind", match=models.MatchExcept(**{"except": SYSTEM_EDGES}))],
should=shoulds
)
res_in, _ = self.client.scroll(self.edges_col, scroll_filter=in_f, limit=500, with_payload=True)
results.extend(res_in)
res_in, _ = self.client.scroll(self.edges_col, scroll_filter=in_filter, limit=500, with_payload=True)
results.extend(res_in)
return results
def _find_connected_edges_batch(self, note_ids):