Themenkomplex |
Volltext-Funktionen |
Funktion |
scanrecs() |
Kurz |
Volltextindext neu erstellen |
Syntax |
ScanRecs(D, I, R, Fields(Felder), ExtABC, Cut, Kontraindex, Modus, Step, MaskenFeld, DynKontraIndex) : INTEGER |
Parameter |
Alle Parameter mit Ausnahme der ersten vier sind optional!
D Tabellennummer der Ausgangstabelle
I Tabellennummer der Stichworttabelle
R Tabellennummer der Relationstabelle
Fields ist ist eine Spezialfunktion, über die die Information, welche Felder in den Volltextindex aufgenommen werden, an die Funktion übergeben werden. Die Feldkombination kann sowohl statisch als auch dynamisch erfolgen. Im Falle der CGI-Programmierung ist nur die dynamische Version möglich, weil hier ja zur Übersetzzeit keine Tabellen geöffnet sind.
Statische Version: Fields(Feld1,Feld2,Feld3...)
Dynamische Version: Fields("Feld1,Feld2,Feld3...")
Es sind alle Felder der Tabelle (mit Ausnahme von Blobs) zugelassen. Datums-, Zeit- und Zahlenfelder werden in Zeichenketten umgewandelt. Bei Auswahlfeldern wird die entsprechende Textkonstante in den Volltext übernommen.
Bei String-Feldern (Zeichenketten) gibt es eine wichtige Ausnahme: Beginnt ein String-Feld mit dem "#"-Zeichen, so wird der Rest der Zeichenkette als Pfad zu einem externen Textdokument interpretiert und dieses in den Volltextindex aufgenommen. Diese Version der tdbengine unterstützt externe ASCII, ANSI und HTML-Dokumente.
Zusätzlich können die Inhalte ADL-verknüpfter Datensätze über die L-Feld-Notation und über die R-Feld-Notation in den Volltextindex aufgenommen werden.
Die optionalen Parameter:
ExtABC
ist eine Zeichenkette, die zusätzlich zu den Buchstaben als Wortbestandteile gelten sollen. Wenn beispielsweise auch die Postleitzahl in den Volltextindex aufgenommen werden sollen, so muß hier "0123456789" stehen.
Tip: Der Bindestrich sollte nicht als Bestandteil eines Wortes aufgenommen werden (außer in Spezialfällen), denn damit werden die einzelnen Bestandteile eines (mit Bindestrichen) zusammengestzten Wortes nicht mehr (so einfach und schnell) über die Volltextsuche auffindbar.
Bei den nächsten beiden Parametern geht es um die Einschränkung des Volltextindex. In vielen Fällen will man nämlich informationsarme Wörter wie "und" "der" u.a. nicht in den Volltextindex aufnehmen.
Cut
wird hier ein Wert größer 0 angegeben, so werden Wörter, die öfter als Cut vorkommen, nicht in den Volltextindex aufgenommen.
Kontraindex
ist der Name eine externen Textdatei, in der jene max. 10.000 Wörter enthalten sind, die nicht in den Volltextindex aufgenommen werden. Dabei steht jedes Wort in einer eigenen Zeile, eine Sortierung ist nicht notwendig.
Der nächste Parameter definiert das grundsätzliche Verhalten der tdbengine bei Aufbauu des Volltextindex. Die einzelnen Modi werden einfach addiert:
Modus
0 | Die Stichworttabelle wird neu erstellt; wird bei "complete" zu 4
| 1 | Eine bestehende Stichworttabelle wird verwendet und nur neue Wörter eingetragen
| 2 | Eine bestehende Stichworttabelle wird verwendet, aber keine neunen Wörter aufgenommen
| 4 *) | Es werden nur die unbedingt benötigten Dateien angelegt
| 8 | HTML-Tags werden überlesen und HTML-Sonderzeichen nach ASCII übersetzt
| 16 | reserviert
| 32 | externe Texte liegen im ASCII-Format vor (andernfalls ANSI)
| 64 | String-Felder, die mit "#" beginnen, werden als Pfade zu externen Dateien interpretiert, die dann in den Volltextindex aufgenommen werden. Beispiel: #/home/html/archiv/12/index.html
| 128 | Es werden nur String- und Memo-Felder indiziert, sonst nix, also keine Zahlen-, Zeit-, Datumsfelder etc. (meist sehr sinnvoll bei "complete"!)
| 256 | Es werden nur die markierten Datensätze in den Volltextindex aufgenommen
| 32768 | Pseudo-0 für "complete"
|
*) Dieser Modus ist nur bedingt kompatibel zum relationalen System der tdbengine. Er ist aber immer dann mit großem Vorteil einzusetzen, wenn der Zugriff auf die Stichworttabelle und die Relationstabelle ausschließlich über die Volltextfunktionen erfolgt. Zudem wird der benötigte Speicherplatz auf weit weniger als 50% reduziert und die Suchgeschwindigkeit signifikant erhöht.
Step
Dieser Parameter ist nur dann auf einen Wert ungleich 0 zu setzen, wenn wirklich sehr große Datenmengen bearbeitet werden. Es handelt sich dabei um den Speicherplatz, den die tdbengine währen des Indizierens vom Betriebssystem anfordert. Viel Speicherplatz bringt in diesem Fall eine erhöhte Bearbeitungsgeschwindigkeit. Allerdings kann eine zu hohe Speicheranforderung dazu führen, daß ein Teil davon vom Betriebssystem ausgelagert wird, was dann zu einem massiven Performance-Einbruch führt! Aber angenommen, sie haben ein 256 Mbyte-System, auf dem nur wenige speicherintensive Prozesse laufen so können Sie beispielsweise hier den Wert 100000000 (=100 Millionen) eingeben.
Tip: Verändern Sie diesen Wert erst dann, wenn die Indizierungszeiten wirklich aus dem Rahmen fallen.
Maskenfeld
Hierbei handelt es sich um die Nummer eines Feldes der Ausgangsdatei, das eine 16-Bit-Integerzahl speichert (NUMBER,2). Der Inhalt dieses Feldes wird in den Volltextindex, genauer in die Relationstabelle (noch genauer: in den IN2 der Relationstabelle) aufgenommen und kann bei der Volltextsuche berücksichtigt werden. Ein Sonderfall besteht, wenn hier -1 angegeben wird, denn dann können die Maskenwerte direkt (durch Doppelpunkt abgetrennt) in der Feldkombination bei Fields angegeben werden. Die Auswertung bei der Volltextsuche geschieht dann dermaßen, daß hier eine Zahl angegeben wird und diese mit einem binären AND mit der im Volltextindex gespeicherten Maske verknüpft wird. Es werden dann nur solche Verknüpfungen gefunden, bei denen das binäre AND einen Wert ungleich 0 ergibt.
Das klingt kompliziert und ist auch kompliziert, eröffnet aber sehr schöne Möglichkeiten. Dazu ein Beispiel. Angenommen Sie haben eine Adreßdatenbank, in der unterschiedliche Arten von Adressen gespeichert sind: Privatadressen, Firmenadressen, Behördern etc. Die Art der Adressen speichern Sie als Kennung in einem Integer-Feld ab:
1 Privat
2 Firma
4 Behörde
8 wissenschaftliche Institution
...
Bei Adressen, die in mehrere Kathegiorien fallen, addieren Sie einfach diese Werte. Wenn Sie nun die Feldnummer dieses Feldes bei der Volltextindizierung mit angeben, so können Sie bereits bei der Suche jede beliebige Einschränkung bezüglich der Kathegorien machen, ohne daß hierzu ein einziger Datensatz gelesen werden muß!
Alternativ zur Auswertung eines Maskenfeldes können Sie auch direkt bei Fields Maskenzahlen vergeben. In diesem Fall hat die Maskenfeldnummer den Wert -1, und die Maskenzahlen werden direkt nach den Feldnamen angegeben. Dazu wieder ein Beispiel:
ScanRecs(D,I,R,Fields("Vorname:1, Name:2,
Strasse:4, Land:8, PLZ:8, Ort:8,
Bemerkung:16"),"",0,"",0,0,-1)
Auch hier wird ein Volltextindex aufgebaut. In die Relationstabelle wird jedoch, wenn es sich bei dem gerade untersuchten Feld um Vorname handelt, zu jedem Eintrag die Maskenzahl 1 aufgenommen, für das Feld Name die Zahl 2 usw. Bei der Volltextsuche können Sie dann gezielt in einzelnen Feldern oder Feldkombinationen suchen (oder natürlich auch in allen Feldern gleichzeitig)!
DynKontraIndex
Hierbei handelt es sich um einen dynamischen, feldbezogenen Kontraindex, der wiederum über die Funktion Fields tranportiert wird. Das bedeutet, daß bei jedem Datensatz zunächst die hier stehenen Felder gelesen werden und daraus ein Kontraindex gebildet wird. Dieser Kontraindex gilt allerdings nur für diesen Datensatz, beim nächsten beginnt das Spiel von vorne. |
Ergebnis |
Die Funktion liefert, falls kein Fehler auftritt, die Anzahl der Einträge in die Relationstabelle. Andernfalls wird ein Laufzeitfehler ausgelöst, den Sie mit .EC 1 abfangen können. |
Siehe auch: |
|
Beschreibung |
Das Beispiel 1 weiter unten enthält alle wesentlichen Bestandteile inklusive skizzierter Fehlerbehandlung.
Darauf sollten Sie achten:
Reihenfolge beim Öffnen der Tabellen, die Relationstabelle immer als Letzte.
Vor ScanRecs Primärtabelle wechseln, damit die Feldbezeichner der Ausgangstabelle erkannt werden.
Und das passiert bei der Volltextindierung:
Zunächst werden sowohl Stichwort- als auch Relationstabelle geleert. Dann werden sämtliche Datensätze der Ausgangstabelle gelesen. Bei jedem Datensatz werden die unter Fields angegebenen Felder gescannt, d.h. in einzelne Zeichenketten zerlegt, die nur aus Buchstaben bestehen. Jeder dieser Wörter wird nun in die Stichworttabelle eingetragen, wenn es dort nicht bereits vorhanden ist. Schließlich erfolgt ein Eintrag in die Relationstabelle mit je einem Verweis auf den Datensatz der Ausgangstabelle und dem zugrhörigen Satz in der Stichworttabelle.
Fehlerbehandlung
Die Parameter erlauben ein sehr flexibles Volltextindizieren beliebiger Datenbestände. Allerdings handelt es sich bei ScanRecs um eine Tabellenfunktion, mit der gleich zwei Tabellen gleichzeitig verändert werden, und entsprechend pingelig ist das System bei der Einhaltung der richtigen Syntax. Die Funktion liefert, falls kein Fehler auftritt, die Anzahl der Einträge in die Relationstabelle. Andernfalls wird ein Laufzeitfehler ausgelöst, den Sie mit .EC 1 abfangen können.
Die häufigsten Fehler:
50: (Unbekannter Bezeichner) In Fields steht mindestens ein falsches Datenfeld
58: (Keine Tabelle) Mindestens eine der drei benötigten Tabellen ist nicht geöffnet
64: (Keine ADL-Tabelle) Die Stichworttabelle wird nicht automatisch numeriert
77: (Keine Relationstabelle) Bei dem dritten Parameter handelt es sich nicht um eine gültige Relationstabelle
Ist das Funktionsergebnis negativ, wird zwar kein Laufzeitfehler ausgelöst, aber die Funktion dennoch abgebrochen
-115 Zu wenig Rechte für die Funktion (Die Relationsdatei konnte nicht geleert werden)
-56 (, erwartet) Die Felder in Fields müssen durch Komma getrennt werden
|
Beispiel 1: Scanrecs
Einfache Volltextindexierung einer Adresstabelle adr.dat
VAR D,I,R,fc,N : INTEGER
SetPara("ec 1")
?fc:=GenList("i-adr.dat",40,1)<>0/HALT .. Error creating index table
?fc:=GenRel("adr","i-adr","r-adr.rel")<>0/HALT .. Error creating relations table
IF D:=OpenDB("adr.dat") THEN
IF I:=OpenDB("i-adr.dat","",0,15) THEN
IF R:=OpenDB("r-adr.rel","",0,15) THEN
PrimFile(D)
N:=ScanRecs(D,I,R,Fields("Firstname,Name,Street,Town,Notice"))
ELSE
..Error opening relations table
END
CloseDB(I)
ELSE
.. Error opening index table
CloseDB(D)
END
ELSE
.. Error opening source table
END
|
|