Ui_Update_cytos
All checks were successful
Deploy mindnet to llm-node / deploy (push) Successful in 3s
All checks were successful
Deploy mindnet to llm-node / deploy (push) Successful in 3s
This commit is contained in:
parent
e93bab6ea7
commit
876ee898d8
|
|
@ -69,20 +69,26 @@ def render_graph_explorer_cytoscape(graph_service):
|
||||||
search_term = st.text_input("Suche Notiz", placeholder="Titel eingeben...", key="cy_search")
|
search_term = st.text_input("Suche Notiz", placeholder="Titel eingeben...", key="cy_search")
|
||||||
|
|
||||||
if search_term:
|
if search_term:
|
||||||
hits, _ = graph_service.client.scroll(
|
try:
|
||||||
collection_name=f"{COLLECTION_PREFIX}_notes",
|
hits, _ = graph_service.client.scroll(
|
||||||
limit=10,
|
collection_name=f"{COLLECTION_PREFIX}_notes",
|
||||||
scroll_filter=models.Filter(must=[models.FieldCondition(key="title", match=models.MatchText(text=search_term))])
|
limit=10,
|
||||||
)
|
scroll_filter=models.Filter(must=[models.FieldCondition(key="title", match=models.MatchText(text=search_term))])
|
||||||
options = {h.payload['title']: h.payload['note_id'] for h in hits}
|
)
|
||||||
|
options = {}
|
||||||
if options:
|
for h in hits:
|
||||||
selected_title = st.selectbox("Ergebnisse:", list(options.keys()), key="cy_select")
|
if h.payload and 'title' in h.payload and 'note_id' in h.payload:
|
||||||
if st.button("Laden", use_container_width=True, key="cy_load"):
|
options[h.payload['title']] = h.payload['note_id']
|
||||||
new_id = options[selected_title]
|
|
||||||
st.session_state.graph_center_id = new_id
|
if options:
|
||||||
st.session_state.graph_inspected_id = new_id
|
selected_title = st.selectbox("Ergebnisse:", list(options.keys()), key="cy_select")
|
||||||
st.rerun()
|
if st.button("Laden", use_container_width=True, key="cy_load"):
|
||||||
|
new_id = options[selected_title]
|
||||||
|
st.session_state.graph_center_id = new_id
|
||||||
|
st.session_state.graph_inspected_id = new_id
|
||||||
|
st.rerun()
|
||||||
|
except Exception as e:
|
||||||
|
st.error(f"Fehler bei der Suche: {e}")
|
||||||
|
|
||||||
st.divider()
|
st.divider()
|
||||||
|
|
||||||
|
|
@ -174,7 +180,12 @@ def render_graph_explorer_cytoscape(graph_service):
|
||||||
st.markdown(f"**ID:** `{inspected_data.get('note_id')}`")
|
st.markdown(f"**ID:** `{inspected_data.get('note_id')}`")
|
||||||
st.markdown(f"**Typ:** `{inspected_data.get('type')}`")
|
st.markdown(f"**Typ:** `{inspected_data.get('type')}`")
|
||||||
with col_i2:
|
with col_i2:
|
||||||
st.markdown(f"**Tags:** {', '.join(inspected_data.get('tags', []))}")
|
tags = inspected_data.get('tags', [])
|
||||||
|
if isinstance(tags, list):
|
||||||
|
tags_str = ', '.join(tags) if tags else "Keine"
|
||||||
|
else:
|
||||||
|
tags_str = str(tags) if tags else "Keine"
|
||||||
|
st.markdown(f"**Tags:** {tags_str}")
|
||||||
path_check = "✅" if inspected_data.get('path') else "❌"
|
path_check = "✅" if inspected_data.get('path') else "❌"
|
||||||
st.markdown(f"**Pfad:** {path_check}")
|
st.markdown(f"**Pfad:** {path_check}")
|
||||||
|
|
||||||
|
|
@ -189,12 +200,27 @@ def render_graph_explorer_cytoscape(graph_service):
|
||||||
# --- GRAPH ELEMENTS ---
|
# --- GRAPH ELEMENTS ---
|
||||||
cy_elements = []
|
cy_elements = []
|
||||||
|
|
||||||
|
# Validierung: Prüfe ob nodes_data vorhanden ist
|
||||||
|
if not nodes_data:
|
||||||
|
st.warning("⚠️ Keine Knoten gefunden. Bitte wähle eine andere Notiz.")
|
||||||
|
# Zeige trotzdem den Inspector, falls Daten vorhanden
|
||||||
|
if inspected_data:
|
||||||
|
st.info(f"**Hinweis:** Die Notiz '{inspected_data.get('title', inspected_id)}' wurde gefunden, hat aber keine Verbindungen im Graphen.")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Erstelle Set aller Node-IDs für schnelle Validierung
|
||||||
|
node_ids = {n.id for n in nodes_data if hasattr(n, 'id') and n.id}
|
||||||
|
|
||||||
|
# Nodes hinzufügen
|
||||||
for n in nodes_data:
|
for n in nodes_data:
|
||||||
|
if not hasattr(n, 'id') or not n.id:
|
||||||
|
continue
|
||||||
|
|
||||||
is_center = (n.id == center_id)
|
is_center = (n.id == center_id)
|
||||||
is_inspected = (n.id == inspected_id)
|
is_inspected = (n.id == inspected_id)
|
||||||
|
|
||||||
tooltip_text = n.title if n.title else n.label
|
tooltip_text = getattr(n, 'title', None) or getattr(n, 'label', '')
|
||||||
display_label = n.label
|
display_label = getattr(n, 'label', str(n.id))
|
||||||
if len(display_label) > 15 and " " in display_label:
|
if len(display_label) > 15 and " " in display_label:
|
||||||
display_label = display_label.replace(" ", "\n", 1)
|
display_label = display_label.replace(" ", "\n", 1)
|
||||||
|
|
||||||
|
|
@ -202,7 +228,7 @@ def render_graph_explorer_cytoscape(graph_service):
|
||||||
"data": {
|
"data": {
|
||||||
"id": n.id,
|
"id": n.id,
|
||||||
"label": display_label,
|
"label": display_label,
|
||||||
"bg_color": n.color,
|
"bg_color": getattr(n, 'color', '#8395a7'),
|
||||||
"tooltip": tooltip_text
|
"tooltip": tooltip_text
|
||||||
},
|
},
|
||||||
# Wir steuern das Aussehen rein über Klassen (.inspected / .center)
|
# Wir steuern das Aussehen rein über Klassen (.inspected / .center)
|
||||||
|
|
@ -211,18 +237,22 @@ def render_graph_explorer_cytoscape(graph_service):
|
||||||
}
|
}
|
||||||
cy_elements.append(cy_node)
|
cy_elements.append(cy_node)
|
||||||
|
|
||||||
for e in edges_data:
|
# Edges hinzufügen - nur wenn beide Nodes im Graph vorhanden sind
|
||||||
target_id = getattr(e, "to", getattr(e, "target", None))
|
if edges_data:
|
||||||
if target_id:
|
for e in edges_data:
|
||||||
cy_edge = {
|
source_id = getattr(e, "source", None)
|
||||||
"data": {
|
target_id = getattr(e, "to", getattr(e, "target", None))
|
||||||
"source": e.source,
|
# Nur hinzufügen, wenn beide IDs vorhanden UND beide Nodes im Graph sind
|
||||||
"target": target_id,
|
if source_id and target_id and source_id in node_ids and target_id in node_ids:
|
||||||
"label": e.label,
|
cy_edge = {
|
||||||
"line_color": e.color
|
"data": {
|
||||||
|
"source": source_id,
|
||||||
|
"target": target_id,
|
||||||
|
"label": getattr(e, "label", ""),
|
||||||
|
"line_color": getattr(e, "color", "#bdc3c7")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
cy_elements.append(cy_edge)
|
||||||
cy_elements.append(cy_edge)
|
|
||||||
|
|
||||||
# --- STYLESHEET ---
|
# --- STYLESHEET ---
|
||||||
stylesheet = [
|
stylesheet = [
|
||||||
|
|
@ -292,43 +322,47 @@ def render_graph_explorer_cytoscape(graph_service):
|
||||||
]
|
]
|
||||||
|
|
||||||
# --- RENDER ---
|
# --- RENDER ---
|
||||||
graph_key = f"cy_{center_id}_{st.session_state.cy_depth}_{st.session_state.cy_ideal_edge_len}"
|
# Nur rendern, wenn Elemente vorhanden sind
|
||||||
|
if not cy_elements:
|
||||||
|
st.warning("⚠️ Keine Graph-Elemente zum Anzeigen gefunden.")
|
||||||
|
else:
|
||||||
|
graph_key = f"cy_{center_id}_{st.session_state.cy_depth}_{st.session_state.cy_ideal_edge_len}"
|
||||||
|
|
||||||
clicked_elements = cytoscape(
|
clicked_elements = cytoscape(
|
||||||
elements=cy_elements,
|
elements=cy_elements,
|
||||||
stylesheet=stylesheet,
|
stylesheet=stylesheet,
|
||||||
layout={
|
layout={
|
||||||
"name": "cose",
|
"name": "cose",
|
||||||
"idealEdgeLength": st.session_state.cy_ideal_edge_len,
|
"idealEdgeLength": st.session_state.cy_ideal_edge_len,
|
||||||
"nodeOverlap": 20,
|
"nodeOverlap": 20,
|
||||||
"refresh": 20,
|
"refresh": 20,
|
||||||
"fit": True,
|
"fit": True,
|
||||||
"padding": 50,
|
"padding": 50,
|
||||||
"randomize": False,
|
"randomize": False,
|
||||||
"componentSpacing": 100,
|
"componentSpacing": 100,
|
||||||
"nodeRepulsion": st.session_state.cy_node_repulsion,
|
"nodeRepulsion": st.session_state.cy_node_repulsion,
|
||||||
"edgeElasticity": 100,
|
"edgeElasticity": 100,
|
||||||
"nestingFactor": 5,
|
"nestingFactor": 5,
|
||||||
"gravity": 80,
|
"gravity": 80,
|
||||||
"numIter": 1000,
|
"numIter": 1000,
|
||||||
"initialTemp": 200,
|
"initialTemp": 200,
|
||||||
"coolingFactor": 0.95,
|
"coolingFactor": 0.95,
|
||||||
"minTemp": 1.0,
|
"minTemp": 1.0,
|
||||||
"animate": False
|
"animate": False
|
||||||
},
|
},
|
||||||
key=graph_key,
|
key=graph_key,
|
||||||
height="700px"
|
height="700px"
|
||||||
)
|
)
|
||||||
|
|
||||||
# --- EVENT HANDLING ---
|
# --- EVENT HANDLING ---
|
||||||
if clicked_elements:
|
if clicked_elements:
|
||||||
clicked_nodes = clicked_elements.get("nodes", [])
|
clicked_nodes = clicked_elements.get("nodes", [])
|
||||||
if clicked_nodes:
|
if clicked_nodes:
|
||||||
clicked_id = clicked_nodes[0]
|
clicked_id = clicked_nodes[0]
|
||||||
|
|
||||||
if clicked_id != st.session_state.graph_inspected_id:
|
if clicked_id != st.session_state.graph_inspected_id:
|
||||||
st.session_state.graph_inspected_id = clicked_id
|
st.session_state.graph_inspected_id = clicked_id
|
||||||
st.rerun()
|
st.rerun()
|
||||||
|
|
||||||
else:
|
else:
|
||||||
st.info("👈 Bitte wähle links eine Notiz aus.")
|
st.info("👈 Bitte wähle links eine Notiz aus.")
|
||||||
|
|
@ -78,7 +78,7 @@ class GraphExplorerService:
|
||||||
# A. Fulltext für Center Node holen (Chunks zusammenfügen)
|
# A. Fulltext für Center Node holen (Chunks zusammenfügen)
|
||||||
center_text = self._fetch_full_text_stitched(center_note_id)
|
center_text = self._fetch_full_text_stitched(center_note_id)
|
||||||
if center_note_id in nodes_dict:
|
if center_note_id in nodes_dict:
|
||||||
orig_title = nodes_dict[center_note_id].title
|
orig_title = getattr(nodes_dict[center_note_id], 'title', None) or getattr(nodes_dict[center_note_id], 'label', '')
|
||||||
clean_full = self._clean_markdown(center_text[:2000])
|
clean_full = self._clean_markdown(center_text[:2000])
|
||||||
# Wir packen den Text in den Tooltip (title attribute)
|
# Wir packen den Text in den Tooltip (title attribute)
|
||||||
nodes_dict[center_note_id].title = f"{orig_title}\n\n📄 INHALT:\n{clean_full}..."
|
nodes_dict[center_note_id].title = f"{orig_title}\n\n📄 INHALT:\n{clean_full}..."
|
||||||
|
|
@ -91,7 +91,8 @@ class GraphExplorerService:
|
||||||
if nid != center_note_id:
|
if nid != center_note_id:
|
||||||
prev_raw = previews.get(nid, "Kein Vorschau-Text.")
|
prev_raw = previews.get(nid, "Kein Vorschau-Text.")
|
||||||
clean_prev = self._clean_markdown(prev_raw[:600])
|
clean_prev = self._clean_markdown(prev_raw[:600])
|
||||||
node_obj.title = f"{node_obj.title}\n\n🔍 VORSCHAU:\n{clean_prev}..."
|
current_title = getattr(node_obj, 'title', None) or getattr(node_obj, 'label', '')
|
||||||
|
node_obj.title = f"{current_title}\n\n🔍 VORSCHAU:\n{clean_prev}..."
|
||||||
|
|
||||||
# Graphen bauen (Nodes & Edges finalisieren)
|
# Graphen bauen (Nodes & Edges finalisieren)
|
||||||
final_edges = []
|
final_edges = []
|
||||||
|
|
@ -167,27 +168,28 @@ class GraphExplorerService:
|
||||||
|
|
||||||
results = []
|
results = []
|
||||||
|
|
||||||
|
if not note_ids:
|
||||||
|
return results
|
||||||
|
|
||||||
# 1. OUTGOING EDGES (Der "Owner"-Fix)
|
# 1. OUTGOING EDGES (Der "Owner"-Fix)
|
||||||
# Wir suchen Kanten, die im Feld 'note_id' (Owner) eine unserer Notizen haben.
|
# 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.
|
# Das findet ALLE ausgehenden Kanten, egal ob sie an einem Chunk oder der Note hängen.
|
||||||
if note_ids:
|
out_filter = models.Filter(must=[
|
||||||
out_filter = models.Filter(must=[
|
models.FieldCondition(key="note_id", match=models.MatchAny(any=note_ids)),
|
||||||
models.FieldCondition(key="note_id", match=models.MatchAny(any=note_ids)),
|
models.FieldCondition(key="kind", match=models.MatchExcept(**{"except": SYSTEM_EDGES}))
|
||||||
models.FieldCondition(key="kind", match=models.MatchExcept(**{"except": SYSTEM_EDGES}))
|
])
|
||||||
])
|
# Limit erhöht, um alle Kanten zu finden
|
||||||
# Limit hoch, um alles zu finden
|
res_out, _ = self.client.scroll(self.edges_col, scroll_filter=out_filter, limit=2000, with_payload=True)
|
||||||
res_out, _ = self.client.scroll(self.edges_col, scroll_filter=out_filter, limit=500, with_payload=True)
|
results.extend(res_out)
|
||||||
results.extend(res_out)
|
|
||||||
|
|
||||||
# 2. INCOMING EDGES (Ziel = Chunk ID oder Titel oder Note ID)
|
# 2. INCOMING EDGES (Ziel = Chunk ID oder Titel oder Note ID)
|
||||||
# Hier müssen wir Chunks auflösen, um Treffer auf Chunks zu finden.
|
# Hier müssen wir Chunks auflösen, um Treffer auf Chunks zu finden.
|
||||||
|
|
||||||
# Chunk IDs der aktuellen Notes holen
|
# Chunk IDs der aktuellen Notes holen (Limit erhöht)
|
||||||
chunk_ids = []
|
chunk_ids = []
|
||||||
if note_ids:
|
c_filter = models.Filter(must=[models.FieldCondition(key="note_id", match=models.MatchAny(any=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=1000, with_payload=False)
|
||||||
chunks, _ = self.client.scroll(self.chunks_col, scroll_filter=c_filter, limit=300)
|
chunk_ids = [c.id for c in chunks]
|
||||||
chunk_ids = [c.id for c in chunks]
|
|
||||||
|
|
||||||
shoulds = []
|
shoulds = []
|
||||||
# Case A: Edge zeigt auf einen unserer Chunks
|
# Case A: Edge zeigt auf einen unserer Chunks
|
||||||
|
|
@ -195,42 +197,66 @@ class GraphExplorerService:
|
||||||
shoulds.append(models.FieldCondition(key="target_id", match=models.MatchAny(any=chunk_ids)))
|
shoulds.append(models.FieldCondition(key="target_id", match=models.MatchAny(any=chunk_ids)))
|
||||||
|
|
||||||
# Case B: Edge zeigt direkt auf unsere Note ID
|
# 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)))
|
||||||
shoulds.append(models.FieldCondition(key="target_id", match=models.MatchAny(any=note_ids)))
|
|
||||||
|
|
||||||
# Case C: Edge zeigt auf unseren Titel (Wikilinks)
|
# Case C: Edge zeigt auf unseren Titel (Wikilinks) - auch wenn note_title None ist, versuchen wir es mit den Titeln der Notes
|
||||||
if note_title:
|
if note_title:
|
||||||
shoulds.append(models.FieldCondition(key="target_id", match=models.MatchValue(value=note_title)))
|
shoulds.append(models.FieldCondition(key="target_id", match=models.MatchValue(value=note_title)))
|
||||||
|
else:
|
||||||
|
# Fallback: Lade Titel der Notes, wenn note_title nicht übergeben wurde
|
||||||
|
for nid in note_ids:
|
||||||
|
note = self._fetch_note_cached(nid)
|
||||||
|
if note and note.get("title"):
|
||||||
|
shoulds.append(models.FieldCondition(key="target_id", match=models.MatchValue(value=note.get("title"))))
|
||||||
|
|
||||||
if shoulds:
|
if shoulds:
|
||||||
in_filter = models.Filter(
|
in_filter = models.Filter(
|
||||||
must=[models.FieldCondition(key="kind", match=models.MatchExcept(**{"except": SYSTEM_EDGES}))],
|
must=[models.FieldCondition(key="kind", match=models.MatchExcept(**{"except": SYSTEM_EDGES}))],
|
||||||
should=shoulds
|
should=shoulds
|
||||||
)
|
)
|
||||||
res_in, _ = self.client.scroll(self.edges_col, scroll_filter=in_filter, limit=500, with_payload=True)
|
# Limit erhöht, um alle eingehenden Kanten zu finden
|
||||||
|
res_in, _ = self.client.scroll(self.edges_col, scroll_filter=in_filter, limit=2000, with_payload=True)
|
||||||
results.extend(res_in)
|
results.extend(res_in)
|
||||||
|
|
||||||
return results
|
return results
|
||||||
|
|
||||||
def _find_connected_edges_batch(self, note_ids):
|
def _find_connected_edges_batch(self, note_ids):
|
||||||
# Wrapper für Level 2 Suche
|
# Wrapper für Level 2 Suche - lade Titel für alle Notes
|
||||||
return self._find_connected_edges(note_ids)
|
note_titles = []
|
||||||
|
for nid in note_ids:
|
||||||
|
note = self._fetch_note_cached(nid)
|
||||||
|
if note and note.get("title"):
|
||||||
|
note_titles.append(note.get("title"))
|
||||||
|
# Verwende den ersten Titel als Fallback (oder None, wenn keine gefunden)
|
||||||
|
title = note_titles[0] if note_titles else None
|
||||||
|
return self._find_connected_edges(note_ids, note_title=title)
|
||||||
|
|
||||||
def _process_edge(self, record, nodes_dict, unique_edges, current_depth):
|
def _process_edge(self, record, nodes_dict, unique_edges, current_depth):
|
||||||
"""Verarbeitet eine rohe Edge, löst IDs auf und fügt sie den Dictionaries hinzu."""
|
"""Verarbeitet eine rohe Edge, löst IDs auf und fügt sie den Dictionaries hinzu."""
|
||||||
|
if not record or not record.payload:
|
||||||
|
return None, None
|
||||||
|
|
||||||
payload = record.payload
|
payload = record.payload
|
||||||
src_ref = payload.get("source_id")
|
src_ref = payload.get("source_id")
|
||||||
tgt_ref = payload.get("target_id")
|
tgt_ref = payload.get("target_id")
|
||||||
kind = payload.get("kind")
|
kind = payload.get("kind")
|
||||||
provenance = payload.get("provenance", "explicit")
|
provenance = payload.get("provenance", "explicit")
|
||||||
|
|
||||||
|
# Prüfe, ob beide Referenzen vorhanden sind
|
||||||
|
if not src_ref or not tgt_ref:
|
||||||
|
return None, None
|
||||||
|
|
||||||
# IDs zu Notes auflösen
|
# IDs zu Notes auflösen
|
||||||
src_note = self._resolve_note_from_ref(src_ref)
|
src_note = self._resolve_note_from_ref(src_ref)
|
||||||
tgt_note = self._resolve_note_from_ref(tgt_ref)
|
tgt_note = self._resolve_note_from_ref(tgt_ref)
|
||||||
|
|
||||||
if src_note and tgt_note:
|
if src_note and tgt_note:
|
||||||
src_id = src_note['note_id']
|
src_id = src_note.get('note_id')
|
||||||
tgt_id = tgt_note['note_id']
|
tgt_id = tgt_note.get('note_id')
|
||||||
|
|
||||||
|
# Prüfe, ob beide IDs vorhanden sind
|
||||||
|
if not src_id or not tgt_id:
|
||||||
|
return None, None
|
||||||
|
|
||||||
if src_id != tgt_id:
|
if src_id != tgt_id:
|
||||||
# Nodes hinzufügen
|
# Nodes hinzufügen
|
||||||
|
|
@ -245,7 +271,7 @@ class GraphExplorerService:
|
||||||
# Bevorzuge explizite Kanten vor Smart Kanten
|
# Bevorzuge explizite Kanten vor Smart Kanten
|
||||||
is_current_explicit = (provenance in ["explicit", "rule"])
|
is_current_explicit = (provenance in ["explicit", "rule"])
|
||||||
if existing:
|
if existing:
|
||||||
is_existing_explicit = (existing['provenance'] in ["explicit", "rule"])
|
is_existing_explicit = (existing.get('provenance', '') in ["explicit", "rule"])
|
||||||
if is_existing_explicit and not is_current_explicit:
|
if is_existing_explicit and not is_current_explicit:
|
||||||
should_update = False
|
should_update = False
|
||||||
|
|
||||||
|
|
@ -275,25 +301,49 @@ class GraphExplorerService:
|
||||||
try:
|
try:
|
||||||
# Versuch 1: Chunk ID direkt
|
# Versuch 1: Chunk ID direkt
|
||||||
res = self.client.retrieve(self.chunks_col, ids=[ref_str], with_payload=True)
|
res = self.client.retrieve(self.chunks_col, ids=[ref_str], with_payload=True)
|
||||||
if res: return self._fetch_note_cached(res[0].payload.get("note_id"))
|
if res and res[0].payload:
|
||||||
except: pass
|
note_id = res[0].payload.get("note_id")
|
||||||
|
if note_id:
|
||||||
|
note = self._fetch_note_cached(note_id)
|
||||||
|
if note: return note
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
# Versuch 2: NoteID#Section (Hash abtrennen)
|
# Versuch 2: NoteID#Section (Hash abtrennen)
|
||||||
possible_note_id = ref_str.split("#")[0]
|
possible_note_id = ref_str.split("#")[0]
|
||||||
if self._fetch_note_cached(possible_note_id): return self._fetch_note_cached(possible_note_id)
|
note = self._fetch_note_cached(possible_note_id)
|
||||||
|
if note: return note
|
||||||
|
|
||||||
# Fall B: Note ID direkt
|
# Fall B: Note ID direkt
|
||||||
if self._fetch_note_cached(ref_str): return self._fetch_note_cached(ref_str)
|
note = self._fetch_note_cached(ref_str)
|
||||||
|
if note: return note
|
||||||
|
|
||||||
|
# Fall C: Titel (exakte Übereinstimmung)
|
||||||
|
try:
|
||||||
|
res, _ = self.client.scroll(
|
||||||
|
collection_name=self.notes_col,
|
||||||
|
scroll_filter=models.Filter(must=[models.FieldCondition(key="title", match=models.MatchValue(value=str(ref_str)))]),
|
||||||
|
limit=1, with_payload=True
|
||||||
|
)
|
||||||
|
if res and res[0].payload:
|
||||||
|
self._note_cache[res[0].payload['note_id']] = res[0].payload
|
||||||
|
return res[0].payload
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Fall D: Titel (Text-Suche für Fuzzy-Matching, falls exakte Suche fehlschlägt)
|
||||||
|
try:
|
||||||
|
res, _ = self.client.scroll(
|
||||||
|
collection_name=self.notes_col,
|
||||||
|
scroll_filter=models.Filter(must=[models.FieldCondition(key="title", match=models.MatchText(text=str(ref_str)))]),
|
||||||
|
limit=1, with_payload=True
|
||||||
|
)
|
||||||
|
if res and res[0].payload:
|
||||||
|
self._note_cache[res[0].payload['note_id']] = res[0].payload
|
||||||
|
return res[0].payload
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
# Fall C: Titel
|
|
||||||
res, _ = self.client.scroll(
|
|
||||||
collection_name=self.notes_col,
|
|
||||||
scroll_filter=models.Filter(must=[models.FieldCondition(key="title", match=models.MatchValue(value=ref_str))]),
|
|
||||||
limit=1, with_payload=True
|
|
||||||
)
|
|
||||||
if res:
|
|
||||||
self._note_cache[res[0].payload['note_id']] = res[0].payload
|
|
||||||
return res[0].payload
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def _add_node_to_dict(self, node_dict, note_payload, level=1):
|
def _add_node_to_dict(self, node_dict, note_payload, level=1):
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user