Freitag, 20. August 2010

Anwendungsbeispiel für MULTI_COLUMN_DATASTORE, MDATA und Operatoren ACCUM und WEIGHT

Ist es möglich Dokumenten unterschiedlichen Formats (Dateityps) eine unterschiedliche Gewichtung zu geben? Beispielsweise ist die Vorgabe, dass Dokumente im Format PDF eine höhere Gewichtung erhalten sollen als Dokumente im Format HTML. Mit MULTI_COLUMN_DATASTORE, MDATA und den unterschiedlichen Operatoren wie ACCUM und WEIGHT kann dies möglich gemacht werden. Mehr Informationen zur MDATA-Nutzung und Multicolumn-Datastore finden Sie übrigens im Metadatensuche mit MDATA und im MData Section und MULTI_COLUMN_DATASTORE Blog.
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...

Beliebte Postings