Nehmen wir im folgenden Beispiel die Tabelle DOCUMENTS mit Spalten INHALT und DATEI_TYP.
CREATE TABLE documents
(id NUMBER, datei_typ VARCHAR2(10), INHALT blob);
Danach füllen wir die Tabelle mit unterschiedlichen Inhalten. Wir verwenden eine LOBLOAD-Prozedur, die die Spalteninhalte als Parameter übergibt. Der Dateiname gibt dabei Auskunft über den Inhalt und das Format.
execute lobload(1,'html','inhalt1.html')
execute lobload(2, 'html','inhalt2.html');
execute lobload(3,'PDF','inhalt1.PDF');
execute lobload(4,'PDF','inhalt2.PDF');
Danach erzeugen wir einen Multicolumn-Datastore über die beiden Spalten DATEI_TYP und INHALT, um eine einzige CONTAINS- Abfrage über die beiden Spalten durchzuführen.
Um den Multicolumn-Datastore nutzen zu können, muss zunächst eine Preference erzeugt werden; hier werden die Spalten, welche gemeinsam indiziert werden sollen, konfiguriert. Da nur die Spalte INHALT und nicht die Spalte DATEI_TYP gefiltert werden soll, setzen wir die FILTER-Attribute auf 'N,Y'.
begin
ctx_ddl.create_preference('mds', 'multi_column_datastore');
ctx_ddl.set_attribute('mds', 'columns', 'datei_typ, inhalt');
ctx_ddl.set_attribute('mds', 'filter', 'N,Y');
end;
/
Die Spalten sind nun im Multicolumn-Datastore MDS zusammengeführt. Da die Spalte
DATEI_TYP als Metadatenspalte aufgefasst werden kann und keine Aufarbeitung in Tokens benötigt, definieren wir die entsprechende MDATA-Section für DATEI_TYP.
begin
ctx_ddl.create_section_group('bsg', 'basic_section_group');
ctx_ddl.add_mdata_section('bsg', 'datei_typ', 'datei_typ');
end;
/
Im letzten Schritt erzeugen wir noch den Index IDX auf die Spalte INHALT.
SQL> CREATE INDEX idx ON documents(inhalt) INDEXTYPE IS ctxsys.context
PARAMETERS ('section group bsg datastore mds filter ctxsys.auto_filter');
Index created.
SQL> SELECT err_index_name, err_timestamp, err_textkey, err_text
FROM ctx_user_index_errors ORDER BY err_index_name, err_timestamp;
no rows selected
Überprüfen wir nun die Dokumente auf einen Inhalt zum Beispiel auf "external". Die Dokumente mit ID 1 und 3 enthalten offensichtlich das gesuchte Token.
SQL> SELECT score(1), id, datei_typ
FROM documents WHERE contains(inhalt, 'external', 1)>0;
SCORE(1) ID DATEI_TYP
---------- ---------- ----------
12 1 html
12 3 PDF
Im nächsten Schritt sollen PDF-Dokumente eine höhere Priorität als HTML-Dokumente erhalten. Dazu nutzen wir den Operator MDATA. Zu beachten ist dabei, dass MDATA Sektionen immer case-sensitiv sind. Das bedeutet wir müssen auf "PDF" und "html" abfragen. Zusätzlich liefert das Ergebnis des MDATA-Operators immer den Wert 0 für "keine Treffer" und 100 für "Treffer". Überprüfen wir zuerst das Scoring auf PDF-Formate . Dokument 3 und 4 sind PDF Dokumente und erhalten den Score 100.
SQL> SELECT score(1), id, datei_typ FROM documents
WHERE contains(inhalt, 'mdata(datei_typ, PDF)', 1)>0;
SCORE(1) ID DATEI_TYP
---------- ---------- ----------
100 3 PDF
100 4 PDF
Benutzen wir zusätzlich die Suchabfrage "external" und verbinden wir das Ganze mit dem ACCUM- Operator (hier mit Komma ','). Wir erhalten nun alle PDF-Dokumente und das HTML-Dokument mit dem entsprechenden Suchwort. Dann sieht das Ergebnis der Abfrage folgendermassen aus.
SQL> SELECT score(1), id, datei_typ FROM documents
WHERE contains(inhalt, 'mdata(datei_typ, PDF), external', 1)>0
ORDER BY 1;
SCORE(1) ID DATEI_TYP
---------- ---------- ----------
6 1 html
50 4 PDF
78 3 PDF
Wie arbeitet dabei der Operator ACCUM? Der Operator ACCUM sucht im ersten Schritt nach erfolgreichen Bedingungen und errechnet danach den Score aus der Anzahl der Treffer-Häufigkeit. Bei zwei Bedingungen und Treffer in den beiden Bedingungen (hier PDF und Suchwort) liegt dabei der Scorewert zwischen 51 und 100, ansonsten zwischen 1 und 50.
Um weitere Möglichkeiten aufzuzeigen, kombinieren wir die Abfrage mit einer zusätzlichen Gewichtung (in unserem Fall mit "*2") und nehmen zusätzlich das Format "html" hinzu. Nun können wir folgende Resultate erhalten.
SQL> SELECT score(1), id, datei_typ FROM documents
WHERE contains(inhalt, 'mdata(datei_typ, PDF)*2, mdata(datei_typ, html),
external', 1)>0 ORDER BY 1;
SCORE(1) ID DATEI_TYP
---------- ---------- ----------
25 2 html
39 1 html
50 4 PDF
68 3 PDF
SQL> SELECT score(1), id, datei_typ FROM documents
WHERE contains(inhalt, 'mdata(datei_typ, PDF)*2, mdata(datei_typ, html),
external*2', 1)>0 ORDER BY 1;
SCORE(1) ID DATEI_TYP
---------- ---------- ----------
20 2 html
40 4 PDF
48 1 html
71 3 PDF
Wie man im letzten Beispiel sehen kann, gibt es eine Vielfalt von möglichen Kombinationen. Probieren Sie es einfach aus...