antragstracker/scripts/migrate_fts5.py
Dotty Dotter 2ab8046b78 feat: FTS5 Volltextsuche mit Snippet-Highlighting (#11)
- SQLite FTS5 Virtual Table (vorlagen_fts) über Betreff, Volltext, Zusammenfassung
- Tokenizer unicode61 mit Diakritik-Entfernung
- API: FTS5 MATCH statt LIKE, LIKE als Fallback wenn kein Index
- Snippet-Highlights (<mark>) in Suchergebnissen
- Migrations-Script: scripts/migrate_fts5.py
- 22.337 Einträge indexiert, ~4.200 Treffer für 'Klimaschutz'

Closes #11
2026-04-01 13:17:27 +02:00

89 lines
2.6 KiB
Python

#!/usr/bin/env python3
"""Migrate: Create FTS5 virtual table for full-text search.
Usage:
python scripts/migrate_fts5.py [path/to/tracker.db]
"""
import sqlite3
import sys
from pathlib import Path
def migrate(db_path: str):
conn = sqlite3.connect(db_path)
conn.execute("PRAGMA journal_mode = WAL")
# Check if FTS table already exists
existing = conn.execute(
"SELECT name FROM sqlite_master WHERE type='table' AND name='vorlagen_fts'"
).fetchone()
if existing:
print("⚠️ vorlagen_fts existiert bereits — wird neu aufgebaut")
conn.execute("DROP TABLE IF EXISTS vorlagen_fts")
# Create FTS5 table (content-sync'd with vorlagen + ki_bewertungen)
conn.execute("""
CREATE VIRTUAL TABLE vorlagen_fts USING fts5(
aktenzeichen,
betreff,
volltext,
zusammenfassung,
content='',
contentless_delete=1,
tokenize='unicode61 remove_diacritics 2'
)
""")
# Populate from vorlagen + ki_bewertungen
cursor = conn.execute("""
SELECT v.id, v.aktenzeichen, v.betreff, v.volltext_clean,
kb.begruendung as zusammenfassung
FROM vorlagen v
LEFT JOIN ki_bewertungen kb ON kb.vorlage_id = v.id AND kb.typ = 'zusammenfassung'
""")
batch = []
count = 0
for row in cursor:
batch.append((
row[0], # rowid = vorlage.id
row[1] or '', # aktenzeichen
row[2] or '', # betreff
row[3] or '', # volltext
row[4] or '', # zusammenfassung
))
if len(batch) >= 1000:
conn.executemany(
"INSERT INTO vorlagen_fts(rowid, aktenzeichen, betreff, volltext, zusammenfassung) VALUES (?, ?, ?, ?, ?)",
batch
)
count += len(batch)
print(f" {count} Vorlagen indexiert...")
batch = []
if batch:
conn.executemany(
"INSERT INTO vorlagen_fts(rowid, aktenzeichen, betreff, volltext, zusammenfassung) VALUES (?, ?, ?, ?, ?)",
batch
)
count += len(batch)
conn.commit()
print(f"✅ FTS5-Index erstellt: {count} Vorlagen indexiert")
# Test
test = conn.execute(
"SELECT COUNT(*) FROM vorlagen_fts WHERE vorlagen_fts MATCH 'Klimaschutz'"
).fetchone()[0]
print(f" Test 'Klimaschutz': {test} Treffer")
conn.close()
if __name__ == "__main__":
db = sys.argv[1] if len(sys.argv) > 1 else str(
Path(__file__).resolve().parents[1] / "data" / "tracker.db"
)
print(f"🔄 FTS5-Migration: {db}")
migrate(db)