Querverweis-Übersicht

Querverweis-Übersicht mit Link-Index für große Bäume

Es gibt drei Arten von Übersichten:

  1. Übersicht über alle Daten für den Admin (Admin-Übersicht),
  2. auf einen Stammbaum begrenzte Übersicht (Benutzer-Übersicht) und
  3. auf einen Datensatz bezogene Übersicht in der Detailansicht (Datensatz-Übersicht, als Tab oder Modal).

Die Admin-Übersicht (Verwaltung → LinkEnhancer → Querverweis-Übersicht) ist eine serverseitig paginierte DataTable. Sie listet alle Datensätze auf, die klassische @XREF@-Querverweise oder LinkEnhancer-Links enthalten, mit einer Link-Auflistung pro-Datensatz.

Optionale Filter:

  • referenzierte XREF (nur verfügbar, während ein frischer Link-Index aktiv ist — im Live-Scan-Modus ist das Feld ausgeblendet, da es dort nur ein grober Vorfilter wäre — keine klassischen Referenzen würden gefunden),
  • Datensatz-Typ,
  • Stammbaum und
  • die Anzahl der pro Link-Klasse angezeigten Token (alle / 5 / 10 / 20, Default 5).

Die XREF-Zelle zeigt den Stammbaumnamen als zweite Zeile in dezenter Schrift. Der Datensatz-Typ ist eine eigene sortierbare Spalte. Jedes Inventar-Token wird als kurzer Anzeigekontext (Snippet) mit dem Link-Token selbst in Fett angezeigt.

Admin overview

Optional kann man eine Benutzer-Übersicht pro Baum und eine Datensatz-Übersicht über die ein- und ausgehenden Referenzen pro GEDCOM-Datensatz aktivieren. Die Datensatz-Übersicht zeigt zudem die XREF und ggf. UIDs des Datensatzes an, damit diese Referenzen leichter in Notzen übernommen werden können.

Record overview

Unterstützte Engines

Live-ÜbersichtLink-Index (CLI)
MariaDB / MySQLja (REGEXP-Gate)ja
PostgreSQLja (REGEXP-Gate)ja
SQLite / SQL ServerEingeschränkter Modus — automatischer Fallback auf ein grobes LIKE-Gate + Volltabellen-Scan pro Anfrage (Banner auf der Seite); die exakte Klassifizierung erfolgt weiterhin in PHPnicht verfügbar (braucht REGEXP + MD5) — die CLI beendet sich mit einem Fehler

Funktionsweise

Bei großen Bäumen kann der Live-Regex-Scan über die GEDCOM-Tabellen langsam sein, daher kann die Seite stattdessen einen Link-Index aus drei Modultabellen lesen (der Abschnitt Entwicklung / Projekt-Struktur enthält mehr Details zum Datenbank-Schema):

  • le_record_scan — eine Zeile pro gescanntem Datensatz mit einem MD5-Fingerprint des Datensatztextes
  • le_link_index — eine Zeile pro (Link, Ziel), das im Datensatz gefunden wurde (der zum Build-Zeitpunkt erfasste Anzeigekontext) — das Fundament für Anzeige der eingehenden Querverweise in der Datensatz-Übersicht
  • le_index_meta — einzelne Zeile — der Zustand des letzten vollständigen Index-Laufs
flowchart TD
    CLI["🛠 cli/build-link-index.php<br/>Cron: */30 * * * *"]

    subgraph Scan["🔍 Inkrementeller Scan"]
        FP["MD5-Fingerabdruck<br/>pro Record"]
        DIFF{"🔀 Geändert?<br/>(neu / entfernt)"}
    end

    subgraph Tables["💾 Tabellen"]
        RS[("le_record_scan<br/>file, xref, hash")]
        LI[("le_link_index<br/>token, target, snippet")]
        META[("le_index_meta<br/>last_run, rows")]
    end

    PAGE["📄 XREF-Übersichtsseite"]

    CLI --> Scan
    FP --> DIFF
    DIFF -->|✅ ja| SCAN["PHP-Scan<br/>(XrefsService)"]
    DIFF -->|⏭ nein| SKIP["überspringen"]
    SCAN --> RS
    SCAN --> LI
    CLI --> META

    META -->|"🟢 fresh (< 2 h)"| PAGE
    META -->|"🟠 stale"| LIVE["Live-Regex-Scan"]
    LIVE --> PAGE

    classDef scanStyle fill:#e3f2fd,stroke:#1565C0,stroke-width:2px
    classDef tablesStyle fill:#e8f5e9,stroke:#2E7D32,stroke-width:2px
    classDef decideStyle fill:#fff3e0,stroke:#E65100,stroke-width:2px
    classDef pageStyle fill:#fce4ec,stroke:#C2185B,stroke-width:2px

    class FP scanStyle
    class RS,LI,META tablesStyle
    class DIFF decideStyle
    class PAGE pageStyle

Der Index wird durch build-link-index.php gepflegt:

  • Initialer Build (erster Lauf oder --rebuild): Beide Indextabellen werden zurückgesetzt, alle Scan-Zeilen werden serverseitig in einer Bulk-Statement pro GEDCOM-Tabelle erstellt (schnell, null Zeilentransfer), und nur die Datensätze, die den Link-Vorfilter passieren, werden in PHP gescannt. Der initiale Build ist eine Einmal-Kosten — verwenden Sie einen höheren --limit dafür. Wenn er durch --limit unterbrochen wird, konvergiert der nächste Lauf (der Build ist idempotent).
  • Inkrementelle Läufe (der normale Cron-Fall): Nur Datensätze, deren MD5-Fingerprint sich geändert hat — oder die hinzugefügt/entfernt wurden — werden neu gescannt (cursor chunked), sodass der Job auch auf großen Sites günstig bleibt.

Cron-Beispiel (alle 30 Minuten, max. 2000 Datensätze pro Lauf):

*/30 * * * * cd /path/to/webtrees && php modules_v4/linkenhancer/cli/build-link-index.php --limit=2000 >> /var/log/linkenhancer-index.log 2>&1

Nur ein vollständiger Lauf (ohne --tree), der nicht durch --limit gekürzt wird, markiert den Index als frisch (le_index_meta.last_run). Ein durch --limit gekürzter Lauf setzt dort fort, wo er aufgehört hat; ein --tree-Lauf aktualisiert nur diesen Baum.

Index leeren (Flush)

--flush leert die Indextabellen und beendet sich (kein Rebuild) — für Tests (die Seite auf Live-Scan zwingen) und Wartung (sauberer Neustart bei kaputtem Index):

php modules_v4/linkenhancer/cli/build-link-index.php --flush            # alle Bäume
php modules_v4/linkenhancer/cli/build-link-index.php --flush --tree=5   # nur Baum 5

Das Frische-Flag wird immer zurückgesetzt, sodass die Seite zuverlässig auf den Live-Scan zurückfällt. Der nächste vollständige Lauf ist wieder ein initialer Build (Voll-Scan-Kosten). --flush kombiniert mit --rebuild ist redundant — --rebuild setzt bereits zurück und baut neu.

Die Übersicht und der Index verwenden einen gemeinsamen Vorfilter (einzelne Quelle: XrefsService::linkPrefilterPatterns()):

  • NOTE (Level >= 1) mit @XREF@ oder ](#@-Link, mit Inhalt auf derselben Zeile. Ein NOTE-Wert, der exactly eine Referenz ist (1 NOTE @N5@), ist ein GEDCOM-gemeinsamer Notiz-Pointer — eine strukturelle Referenz, kein Text-Link, und wird nicht aufgelistet.
  • CONC/CONT/TEXT/_TODO mit @XREF@ (nackt ist ein Link) oder ](#@-Link
  • ein LE-Link kann einen optionalen id=@XREF@-Parameter tragen (maximal einer, die Position unter den Parametern ist egal) — wie die wt=-Parameter wird er als Link-Ziel indexiert
  • der eigene Level-0-Text einer gemeinsamen Notiz (0 @N1@ NOTE …)
  • die Übereinstimmung ist zeilenbasiert (keine Cross-Line-Matches), auf denselben Zeilen, die der Collector liest

Die Seite zeigt an, welche Quelle sie verwendet:

  • Index aktiv (grüne Notiz): ein vollständiger, kompletter Index-Lauf ist vor weniger als 2 Stunden beendet (Default; XrefsService::INDEX_FRESH_SECONDS)
  • Live-Scan (blaue Notiz): kein frischer Index — die Seite fällt auf den Live-Scan zurück
  • Eingeschränkter Modus (gelbe Notiz, SQLite/SQL Server): siehe Enginetabelle oben

Verwenden Sie p1-measure.php (read-only) auf Ihrer Instanz, um zu prüfen, wie kostspielig der Live-Scan für Ihre Daten ist und den Cron-Zeitplan zu kalibrieren.

Zuletzt geändert 07.11.2026: support for subpath (c7b1ab7)