Inhaltsverzeichnis
Oracle Text 12c CTXRULE Indexe - Mit Abfrageregeln Dokumente klassifizieren
Verfügbar ab Oracle 9.0.1 - getestet mit Oracle 12c R1
Einführung in Oracle Text ⇒ Oracle Text - Volltext Suche über Text Dokumente
Der CTXRULE Index wird verwendet um in Systemen, die aufgrund von Regeln Dokumente verteilen sollen, das entsprechende Regelwerk aufzubauen. Auf Basis einer Volltext Suche wird dabei das Dokument entsprechenden Klassen zugeordnet.
Der Vorteil liegt darin, dass nicht das eigentliche Dokument zuvor indiziert werden muss, sondern „on the fly“ eine Basis von Regel auf dem Dokument angewendet werden.
Allerdings muss der Inhalt des Dokuments dazu schon als Text (VARCHAR2 oder CLOB) vorliegen, dem "Match" Operator des CTXRULE Index wird dieser Text übergeben und über ein Regelwerk auf Basis der Regeln in einer Tabelle überprüft.
Übersicht:
- Verfügbar ab der Version 9.0.1
- Klassifizierungsregeln auf der Grundlage von Oracle Text Queries
- Indiziert werden die in einer Tabelle gespeicherten Queries
- Klassifiziert Dokumente nach dem Inhalt (anhand der Query), z.B. nach Ressorts wie Sport, Politik, Wirtschaft, etc.
- MATCHES Operator überprüft die Dokumente anhand der definierten Regeln zu, gilt nur beim CTXRULE Index
- Ist der Score > 0 trifft die Regel zu
- Das zu prüfende Dokument:
- Ist selber nicht notwendiger Weise bereits indiziert
- Wird geparsed, wenn MATCHES aufgerufen wird
- Muss nicht in der DB gespeichert werden, muss aber als VACHAR2 oder CLOB übergeben werden können
Ablauf:
- Anlegen einer Tabelle, in der die Regeln für die Dokumenten-Klassifizierung gespeichert werden
- Erstellen der Regeln
- Eigendefinierte Regel über SQL Inserts oder CTX_CLS.TRAIN
- Alternativ - Bekannte Dokumente als eine Art Vorlage für ein Regelwerk verwenden
- Siehe dazu auch in der 12c Dokumentation Supervised Classification
- Anlegen des CXTRULE-Indexes
- Verwendung des MATCHES-Operators, um die Dokumente zu klassifizieren
CTXRULE Index Anlegen
Regel Tabelle anlegen:
CREATE TABLE DOCUMENT_RULES ( id NUMBER(9) PRIMARY KEY ,category VARCHAR2(30) ,query VARCHAR2(2000) ) /
Regeln in der Tabelle hinterlegen, dafür können die folgenden Operatoren verwandt werden: ABOUT, AND, EQUIVALENCE, NEAR, NOT, OR, PHRASE, STEM, WITHIN
Beispiel:
INSERT INTO DOCUMENT_RULES VALUES(1, 'Big data' , 'nosql and database'); INSERT INTO DOCUMENT_RULES VALUES(2, 'Java' , 'ABOUT(Java)'); INSERT INTO DOCUMENT_RULES VALUES(3, 'Python' , 'ABOUT(Phyton)'); commit;
Alternativ kann auch über bestehende, bereits qualifizierte Dokumente mit CTX_CLS.TRAIN ein Regelwerk aufgebaut werden.
Index auf die Regel Tabelle erstellen:
CREATE INDEX idx_ctx_doc_rules ON DOCUMENT_RULES(query) INDEXTYPE IS ctxsys.CTXRULE;
Mit dem Match Operator einen Text abfragen und die entsprechende Regel erkennen:
SELECT category FROM DOCUMENT_RULES WHERE MATCHES(query, 'This text is about nosql and database')>0 / CATEGORY -------- Big DATA
Dokumente damit klassifizieren
Wie gesagt können nur Dokumente überprüft werden die auch als Text im Format VARCHAR2 oder CLOB vorliegen.
In unseren Fall liegen die Dokumente aber noch auf Disk und werden über eine BFILE Pointer Datentyp referenziert.
Die Dokumententabelle sieht prinzipiell daher so aus:
-- CREATE TABLE DOCUMENTS( id NUMBER(11) .. , FILEPOINTER BFILE );
Um die erhaltenen Informationen aus den angewandten Regeln speichern zu können legen wir eine Tabelle für die Klassen der Dokumente an:
CREATE TABLE document_classes ( id NUMBER(11) , doc_id NUMBER(11) , category VARCHAR2(2000) ) / -- sequence for the pk CREATE SEQUENCE document_classes_seq /
Über die in der Regel Tabelle „document_rules“ hinterlegten Abfragen werden die Dokumente dann klassifiziert.
BFILE Dokumente für die Verarbeitung vorbereiten
Hier ein Beispiel für das Auslesen BFILES als BLOB und wandeln mit Oracle Text nach CLOB, erst dann kann die entsprechende Klassifizierung erfolgen:
-- Oracle Text Policy für das Filtern on the fly anlegen BEGIN ctx_ddl.create_preference(preference_name => 'fast_filter' , object_name => 'AUTO_FILTER'); ctx_ddl.set_attribute(preference_name => 'fast_filter' , attribute_name => 'OUTPUT_FORMATTING' , attribute_value => 'FALSE'); ctx_ddl.create_policy(policy_name => 'GPI_FAST_POLICY' , FILTER => 'fast_filter'); END; / -- read the data and classify DECLARE -- The id of the test document v_doc_id NUMBER:=5541; v_doc_text CLOB; v_file_doc bfile; v_blob_doc BLOB; v_amount INTEGER := 32767; v_position INTEGER := 1; v_buffer raw(32767); BEGIN -- read the bfile from the database SELECT filepointer INTO v_file_doc FROM documents WHERE id = v_doc_id; -- create a temporary CLOB to hold the document text dbms_lob.createtemporary(v_blob_doc, TRUE, dbms_lob.session); -- read the bfile to the blob dbms_lob.open(v_file_doc, dbms_lob.lob_readonly); loop BEGIN dbms_lob.read(v_file_doc, v_amount, v_position, v_buffer); exception WHEN no_data_found THEN exit; END; dbms_lob.writeappend(v_blob_doc, v_amount, v_buffer); v_position := v_position + v_amount; END loop; dbms_lob.close(v_file_doc); -- call ctx_doc.policy_filter to filter the BLOB to CLOB data ctx_doc.policy_filter('GPI_FAST_POLICY', v_blob_doc, v_doc_text, FALSE); -- now do the matches query using the CLOB version FOR rec IN (SELECT * FROM document_rules WHERE matches(query, v_doc_text)>0 ) loop -- add results to the document class table dbms_output.put_line('-- Info : found ::'||rec.category); INSERT INTO document_classes (id,doc_id,category ) VALUES (document_classes_seq.nextval,v_doc_id,rec.category ); END loop; dbms_lob.freetemporary(v_blob_doc); END; /
Je nach Anforderung in der Software kann nun diese Logik in einen Trigger auf der eigentlichen Dokumenten Tabelle oder über einen Job (zum Beispiel beim Laden der Dokumente) implementiert werden.
Quellen
Oracle Dokumentation:
Oracle HowTo:
Bfile und Match