Benutzer-Werkzeuge

Webseiten-Werkzeuge


dba:oracle_text

Oracle Text - Volltext Suche über Text Dokumente

In der DB als Option seit Oracle 7

Oracle Text Katze

Oracle Text ist eine der Perlen unter den Optionen der Oracle Datenbank.

Oracle Text, gestartet 1990 als SQL*TextRetrieval™, dann als DB Option mit Oracle Context mit 7.3 verfügbar, eingeführt als Intermedia Text mit der 8i und als Oracle Text Option seit 9i, ist fester Bestandteil des Datenbankkerns und Lizenz-kostenfrei in jeder Oracle Edition verfügbar.

Neben der Möglichkeit den Text in einer Spalte zu indizieren und damit einfach durchsuchbar zumachen, können auch ganze Dokumente, wie MS Word oder PDF, mit mitgelieferten oder eigenen Filtern in Text gewandelt und in den Suchindex aufgenommen werden.

Mit Topic Spotting über Theme Indexes lassen sich Text automatisch nach Themen verschlagworten und kategorisieren.

Dazu können sogar eigene Ontologie hinterlegt werden, um eine eigene sprachliche Begriffswelt abzubilden.

Auf diesen Daten lassen sich dann mit Oracle Text komplexe linguistische Abfragen durchführen, von einfachen like suchen bis zu komplexen Fuzzy Pattern Matchings.

Durch die vollständige Integration in SQL können auch komplexe Rechtevorgaben auf Daten einfach und integriert umgesetzt werden.

Gerade in 12c sind wieder neue spannende Features, wie der „near Realtime Index“ dazugekommen, um Oracle Text noch einfacher einzusetzen.


Die wichtigsten Begriffe rund um Oracle Text

Kurzer Überblick über die wichtigsten Begriffe im Zusammenhang mit Oracle Text

Token

  • Durch Tokenizing wird der „rohe“ natürlich-sprachliche Text aus dem Korpus entlang der Wortgrenzen in einzelne Tokens zerlegt, die idealerweise Lexemen entsprechen
  • Lexem ⇒ sprachliche Bedeutungseinheit
  • Beispiel: Suche nach „Web-site“ findet genau „Website“
  • Der Lexer zerlegt den Text in Token

Stemmer bzw. Stemming

  • Mittels eines morphologischen Ersatzverfahrens (Stemming) werden die Token normalisiert. Dazu werden die vom Tokenizer ermittelten Lexeme auf Stämme reduziert, die idealerweise morphologisch fundierten Wortstämmen entsprechen
  • Beispiel: Suche nach „läuft“ findet auch ⇒ „laufen“, „lief“

Thesaurus

  • Wörterbuch aus Relationen zwischen Lexemen
  • Beispiel: Suche nach „PKW“ findet auch „Auto“ (Relation Synonym)

Theme

  • Kowledge base, hierarchical tree of concepts (Basis für den Theme Index)
  • Eine „Begriffswelt aus Werten“ über eine Ontologie kann helfen den Inhalt eines Dokumentes zu beschreiben
  • Beispiel: Begriffswelt „SQL Oracle Context Index“ beschreibt alle Dokumente über Oracle Text ⇒ Bei einer Suche nach „Index“ werden alle Dokumente gefunden, auch wenn Index nicht als Wort vorkommt.
  • Wird auf der Basis eines vorhandenen Thesaurus erstellt

Fuzzy Suche

  • Bedeutet soviel wie „undeutlich“, „verschwommen“ oder „unscharf“
  • Erweiterung der gewöhnlichen Mengenlehre
  • Beispiel: Suche nach „Kamdurga“ findet auch „Hamburger“

Gist

  • Zusammenfassung eines Dokuments

Die Oracle Soundex Funktion für Phonetischer Vergleich hat nichts mit Oracle Text zu tun, hier werden Wörter über einen einfachen Algorithmus verglichen, siehe ⇒ Mit Soundex Wörter in der Datenbank vergleichen, neben Soundex stehen noch die Jaro Winkler Funktion - Strings vergleichen und Ähnlichkeiten in String qualifizieren zur Verfügung.


Ein erster einfacher Einsatz

Oracle Text verwendet einen speziellen Index Typ, im einfachsten Fall den Typ „CTXSYS.CONTEXT“

Beispiel:

 Ein einfaches erstes Oracle Text Beispiel

Unterstützte Datentypen: VARCHAR2, BLOB, CLOB, CFILE (Historisch LONG, LONG RAW )

Der Text in den Spalten muss allerdings im einfachen Fall immer als Text vorliegen, sollen Binäre Dokumente indiziert werden müssen externe Filter dazu eingebunden werden.

Abgefragt werden die Daten dann mit dem Oracle Text CONTAINS Operator (siehe Abschnitt über Oracle Datenbank Operatoren, mehr dazu unter Oracle Text - In Texten suchen

Der Oracle Context Index wird allerdings NICHT zusammen mit einer DML Operation auf den Text per Default aktualisiert.

Wird der Text einer indizierten Spalte geändert oder gelöscht, merkt sich Oracle Text das nur in einer Pending Tabelle.

Erst beim nächsten Aufruf von „ctx_ddl.sync_index('<index_name>', '<Memory wie 2M>');“ wird die Änderung in den Index aufgenommen.

Die Daten eines gelöschten Dokumentes werden allerdings nicht bereinigt, d.h. nach einer gewissen Zeit bei Tabellen mit hohen Änderungsvolumen ist ein kompletter Neuaufbau sehr sinnvoll.


Oracle Text Index Typen

Folgende Index Typen stehen uns für die Indizierung zur Verfügung:

CONTEXT

  • Textrecherche mit CONTAINS Operator
  • Umfangreiche Parameter und Features
  • Muss nach DML mit CTX_DDL.SYNC_INDEX aktualisiert werden
  • Suche mit dem CONTAINS Operator
  • Neu mit 12c ⇒ „near Realtime Index“ Feature über storage preference „STAGE_ITAB“ auf „true“

CTXCAT

  • Einfachere Version für kleine Mengen von Dokumenten
  • In Transaktionslogik eingebunden
  • Suche mit dem CATSEARCH Operator

CTXRULE

CTXXPATH (Desupported in Oracle Text and Oracle XML DB mit der Version 12c!)

  • XML Datentypen schneller mit ExistsNode() abfragen

Aufbau des Index Typ CONTEXT

Alle Index Typen von Oracle Text verwenden Datenbank Tabellen um den eigentlichen logischen Index abzubilden. Auf diesen Hilfstabellen (DR$<index_name>$<I|K|N|R|P) können zum Teil wieder normale Indexe (mit einer Eigenschaft beim Erzeugen des Indexes) zur Performance Optimierung angelegt werden

Zum Beispiel werden für einen Index vom Typ CTXSYS.Context und mit dem Namen „IDX_DOCUMENTS_DOCS min. die folgenden 4 Tabellen erstellt:

  • DR$IDX_DOCUMENTS_DOCS$I (invertierte Liste aller Wörter)
  • DR$IDX_DOCUMENTS_DOCS$K (Key Map)
  • DR$IDX_DOCUMENTS_DOCS$N (NEG - Gelöschte Datensätze vermerken)
  • DR$IDX_DOCUMENTS_DOCS$R (Denormalisierte Mapping-Tabelle )
    • Optional: DR$IDX_DOCUMENTS_DOCS$P (Substrings)
    • Optional: DR$IDX_DOCUMENTS_DOCS$O (ab 12c Forward Indexing für Highlightning, Snippet,Markup Function)
    • Optional: DR$IDX_DOCUMENTS_DOCS$D (ab 12c Forward Indexing , kompletter Text als PlainText Spalte für Higlighting, Snippet,Markup function für binäre Dokumente)
    • Optional: DR$IDX_DOCUMENTS_DOCS$G (ab 12c für das Feature Near Real Time Indexes verwendet)

Ein Pipline Prozess füllt diese Strukturen im Index beim Anlegen bzw. aktualisieren.

 Der Pipeline-Prozess beim Anlegen beim Anlegen eines Oracle Text Indexes

Für alle diese Abschnitte können beim Anlegen eines Context Indexes dann entsprechend die Eigenschaften eingestellt werden, siehe dazu in der Dokumentation ⇒ https://docs.oracle.com/database/121/CCREF/cdatadic.htm#CCREF0200

Mehrsprachigkeit mit MULTI_LEXER

Was passiert beim Einfügen eines neuen Textes?

 Oracle Text - Was passiert beim einfügen


Wörter aus den Index verbannen - Stop Words definieren

Welche Wörter werden per Default nicht indiziert:

SELECT * FROM ctxsys.ctx_stopwords  
 WHERE spw_stoplist LIKE 'DEFAULT_STOPLIST'
ORDER BY spw_word;

Auslesen per Package siehe auch http://blog.mclaughlinsoftware.com/oracle-text-programming/reading-a-ctx-index-stoplist/

Eine eigenen StopWord Liste läßt sich auch anlegen:

EXEC  ctx_ddl.create_stoplist('GPI_STOPLIST','BASIC_STOPLIST');
EXEC  ctx_ddl.add_stopword('GPI_STOPLIST','10');
...

Im laufenden Betrieb einfügen:

ALTER INDEX idx_doc_files PARAMETERS('ADD STOPWORD gpi');

Stop Word wieder entfernen:

EXEC ctx_ddl.remove_stopword('GPI_STOPLIST', 'gpi'); 

12c Pattern Stopclass

Entferne alle Zahlen die länger als 4 Zeichen sind:

EXEC ctx_ddl.add_stopclass  ('GPI_STOPLIST', 'NUM_GT_4', '[[:digit:]\,\.]{5,}')

Dokumente in der Datenbank speichern

Nur im einfachsten Fall liegen Dokument immer schon bereits als reine Text Dateien vor.

Wir können dann die Dokumente als VARCHAR2 Text Spalte mit 4.000 Zeichen oder in CLOB Spalten (Maximale Größe ist (4 gigabytes - 1) * (database block size)) speichern.

Seit 12c kann auch die Datenbank umgestellt werden, es können dann bis zu 32767 Zeichen in einer Varchar2 Tabellen Spalte abgelegt werden, Dazu muss der Parameter max_string_size aber auf EXTENDED geändert werden, das kann wiederum nicht online durchgeführt werden ⇒ ORA-14694: database must in UPGRADE mode to begin MAX_STRING_SIZE migration.

Liegen die Daten binär vor, steht uns der Dateityp BLOB zur Verfügung, ab 11g sollte diese LOB Spalten als LOB und Oracle Secure Files abgelegt werden. Diese können dann komprimiert und de-dupliziert werden.

Alternativ können die Dateien aber einfach auch im Filesystem verbleiben und werden mit einen BFILE Datentyp über ein Oracle Directory Objekte referenziert.

Wie in diesen Beispiel werden dann nur die File Pointer in der DB gespeichert und indiziert, Siehe ⇒ Mit Python Referenzen für alle Dateien einer Verzeichnisstruktur in der Oracle Datenbank speichern


Binäre Daten indizieren

Mit dem Update auf die Version Oracle Text 11g Release 1 wurde von den Filtern der Firma Inso auf die Filter der Firma Stellent umgestellt. Der Name der Filter Option wurde von INSO_FILTER auf AUTO_FILTER angepasst.

Damit das aber rückwärts kompatibel bleibt, gibt es auch weiterhin die INSO_FILTER Option, allerdings sollte stattdessen immer mit AUTO_FILTER bei neuen Applikationen gearbeitet werden.

In der Version 12c R1 können diese Filter auf diesen Plattformen und diesen Dokumenttypen angewandt werden.

Damit steht uns die Technologie unter Windows und Linux zur Verfügung und es können die wichtigsten MS Office Formate (offiziell bis zur Version 2010) und PDF gelesen werden.

Ein erster Test um den Filter zu testen, wir wandeln eine Powerpoint Datei 2013 in eine HMTL Datei (ohne Bilder) um:

#Windows Powershell Syntax!
#Oracle Home setzen
 
& $env:ORACLE_HOME/bin/ctxhx.exe
 
& $env:ORACLE_HOME/bin/ctxhx.exe d:\doag\apex_connect2016.pptx d:\temp\output_data.html

Mehr Informationen dazu siehe Oracle Text für die Indizierung binärer Daten verwenden

Alternativ sollte der Einsatz von PROCEDURE_FILTER angedacht werden.


Einen Theme Index aufbauen

Mit Hilfe eines Theme Indexe lässt sich der Inhalt eines Dokumentes besser verstehen, über ein Regelwerk schließen wir auf die ungefähre Bedeutung des Dokuments.

Allerdings benötigen wir für eine solche Analyse ein entsprechendes Regelwerk, eine Ontologie.

Für die Englisch liegt zwar einiges breits vor, für Deutsch muss aber selber ein Regelwerk aufgestellt werden.

Für den Theme Index wird ein Oracle Context Index mit einer eigen Eigenschaft für den Lexer (INDEX_THEMES) angelegt.

Siehe Oracle Text Theme Indizierung von Dokumenten


Mit einem Thesaurus und Oracle Text arbeiten

Über einen Thesaurus werden Relationen zwischen Wörtern abgebildet.

Eine Typische Relation ist das strikte Synonym (SN) wie „Apfelsine“ „Orange“, das heißt beide Begriffe stehen in der Hauptsache tatsächlich für das gleiche. Die Begriffe können aber im Textkontext durchaus eine andere Bedeutungs-Färbung entfalten.

In der Sprache gibt es im Regelfall selten zwei Wörter für exakt die gleiche Bedeutung.

Allerdings gibt es viele Verwandtschaftsgrade zwischen verschiedenen Wörtern, die eine ähnliche Bedeutung im Text Kontext entfalten können und eine zusätzliche Wertung enthalten.

Alles diese Beziehung können in eine Thesaurus modelliert werden und dann über Oracle Text auch auf den Text zur Suche verwendet werden.

Allerdings stehen diese Thesaurus nur für wenige Sprache wie Englisch zur Verfügung, meist muss ein eigener Thesaurus erstellt werden.

Auch passen allgemeine Thesaurus oft gar nicht so zur eigentlichen Aufgabe, wie das Finden von alternativen Beziehungen in Fachdokumenten.

Ein Thesaurus ist dann wiederum die Voraussetzung das ein Dokument über einen Oracle Theme Index indiziert und gesucht werden kann.

Da die Definition diese Regel doch sehr anspruchsvoll werden kann, ist ein sehr sinnvoller Einsatz in der Klassifizierung von Dokumenten zu finden, z.b. über den CTX Rule Index.

Im Detail siehe Mit einem Thesaurus und Oracle Text arbeiten


Der Oracle Text Contains Operator

Die eigentliche Volltext Suche in SQL wird über den Contains Operator durchgeführt.

Generelle Syntax:

SELECT id
     , SCORE(1) 
  FROM TEXTE
 WHERE CONTAINS(COLUMN, 'query_string',1)>0
/
 
-- Beispiel für die fussy Suchen in der ausführlichen Variante
 
SELECT * FROM texte WHERE contains(text, 'fuzzy(Hunt, 50, 50, WEIGHT)') >0;

Über die SCORE Funktion kann die Relevance eines Treffers in der Ergebnismenge mit angezeigt werden.

Im Detail Siehe auch dazu ⇒ Oracle Text - In Texten suchen


Die Ergebnisse der Suchen markieren / hervorheben

Nach dem ein Dokument mit einer Volltext Suche gefunden wurde, stellt sich natürlich die Frage, wo den im Text etwas erkannt wurde.

Für die Aufbereitung der Trefferliste/Dokumentanzeige wird dazu das CTX_DOC Package eingesetzt.

So kann zum Beispiel mit „CTX_DOC.SNIPPET“ der Treffer Text Abschnitt angezeigt werden:

Siehe auch dazu ⇒ Oracle Text - Die Treffer in der Ergebnismenge hervorheben


Oracle Text Funktionen in PL/SQL für binäre Dokumente verwenden

Neben der Hauptfunktion der Volltext Suche können die Oracle Text Feature auch in PL/SQL für das arbeiten mit Binären Dokumente verwendet werden.

Zum Beispiel einen Vorschauansicht eines binären Dokumentes wie MS Word in Apex darzustellen oder Daten auszulesen und zu verarbeiten.

Dazu kann sehr gut das CTX_DOC Package eingesetzt werden.

Siehe auch dazu ⇒ Oracle Text für die Verarbeitung von Binären Daten in PL/SQL verwenden


Mit Oracle Text über mehrere Tabellenspalten oder Tabellen suchen

Für einen Anwender ist es oft sehr praktisch in einer Suchmaske über mehrere Datenbank Felder hinweg zu suchen.

Mit der „DATASTORE“ Eigenschaft des Index lässt sich definieren wo die Daten liegen, wichtig ist es einen eindeutigen Primary Key für den späteren Zugriff auf die Daten zur Verfügung zu haben.

Mit Oracle Text mehrere Spalten mehrerer Tabellen indizieren


Installation von Oracle Text in der Datenbank

Am einfachsten ist die Installation gleich zu Beginn bei der Datenbank Installation.

Nachträglich kann unter 11g Oracle Text mit SQL*Plus nach installiert werden (evtl. auch mit 12c ohne Multi/Single Tenant möglich aber nicht mehr supported!):

#set DB enviroment
cd $ORACLE_HOME/rdbms/admin
sqlplus / AS sysdba
spool /tmp/oracle_text_install.log
@?/ctx/admin/catctx.sql ctxsys_pwd_changeon_install SYSAUX TEMP NOLOCK
exit
 
#load LANGUAGE settings
 
sqlplus ctxsys/ctxsys_pwd_changeon_install
 
@?/ctx/admin/defaults/dr0defin.sql "GERMAN";
 
exit
 
#Lock the account FOR security
sqlplus / AS sysdba
ALTER USER ctxsys account LOCK password expire;
 
#check:
elect comp_name, STATUS, substr(version,1,10) AS version FROM dba_registry WHERE comp_id = 'CONTEXT';
SELECT * FROM ctxsys.ctx_version;
SELECT object_name, object_type, STATUS FROM dba_objects WHERE owner='CTXSYS' AND STATUS != 'VALID' ORDER BY object_name;

Siehe auch dazu Support Note: 11g R2 - ID 970473.1, siehe für 12c ID 1666831.1 - nur noch Database Configuration Assistant (DBCA) offizell möglich.

Allerdings sollten vor der Verwendung noch die jeweiligen Parameter von Oracle Text optimiert und eingestellt werden.


Überwachung

Analyse Script

Die Oracle Text Eigenschaften in der DB Abfragen und ein SQL für die Anlayse der Oracle Text Indexes erstellen:

ctx.sql
SET verify  off
SET linesize 120 pagesize 4000 recsep OFF
 
define USER_NAME = &1 
 
ttitle LEFT  "Oracle Text Indexes for the user &&USER_NAME." skip 2
 
COLUMN idx_owner  format a15 heading "Qwner" 
COLUMN TABLE_NAME format a35 heading "Table/View Name"
COLUMN idx_name   format a25 heading "Name" 
COLUMN idx_status format a8 heading  "Status" 
COLUMN idx_type   format a12 heading "Index Type" 
 
SELECT idx_owner
      ,idx_name
	  ,idx_table_owner||'.'||idx_table AS TABLE_NAME
	  ,idx_status
	  ,idx_type
 FROM ctxsys.ctx_indexes 
 WHERE UPPER(idx_owner) IN (UPPER('&&USER_NAME.'))
/ 
 
--
-- create the CTX_REPORT.DESCRIBE_INDEX sql's
--
 
SET long 64000
SET pages 0
SET heading off
SET feedback off
spool get_ctx_desc_report.sql
prompt SET long 64000
prompt SET longchunksize 64000
prompt SET head off
prompt SET echo ON
prompt spool ctx_desc_report.txt
SELECT 'select ctx_report.describe_index('''||idx_owner||'.'||idx_name||''') from dual;'
  FROM ctxsys.ctx_indexes 
 WHERE UPPER(idx_owner) IN (UPPER('&&USER_NAME.'))
/
prompt spool off
prompt exit
spool off
 
-- create the anlyse script
spool get_ctx_stat_report.sql
prompt SET echo ON
prompt SET serveroutput ON
prompt CREATE TABLE ctx_report_output (ctx_name varchar2(40), RESULT CLOB)
prompt /
prompt
prompt DECLARE
prompt     x CLOB := NULL;;
prompt   BEGIN
prompt      ctx_output.start_log('ix_search_stats.log');;
SELECT   '  ctx_report.INDEX_STATS('''||idx_owner||'.'||idx_name||''',x);'
       ||chr(10)
	   ||'  insert into ctx_report_output values ('''||idx_name||''',x);'
	   ||chr(10)
	   ||'  commit;'
  FROM ctxsys.ctx_indexes 
 WHERE UPPER(idx_owner) IN (UPPER('&&USER_NAME.'))
/
prompt     ctx_output.end_log;;
prompt     dbms_lob.freetemporary(x);;
prompt  END;;
prompt /
prompt
prompt SET long 64000
prompt SET longchunksize 64000
prompt SET head off
prompt SET pagesize 10000
prompt spool ctx_stat_report.txt
prompt SELECT RESULT 
prompt  FROM ctx_report_output
prompt / 
prompt spool off
prompt exit
spool off
 
SET pages 100
SET heading ON
SET feedback ON
 
prompt ... TO GET the FULL informations OVER the indexes CALL the generated
prompt ... SQL report @get_ctx_desc_report.sql 
prompt
prompt ... TO GET the statistic informations OVER the indexes CALL the generated 
prompt ... SQL report @get_ctx_stat_report.sql 
prompt ...
prompt ... CHECK FOR the run IF the log directory ORACLE_HOME/ctx/log exits!
prompt ...
 
ttitle LEFT  "Oracle Text Parameters" skip 2
 
COLUMN par_name  format a25 heading "Parameter" 
COLUMN par_value format a30 heading "Value" 
 
SELECT par_name
     , par_value
 FROM ctxsys.ctx_parameters
ORDER BY 1 
/ 
 
ttitle LEFT  "Oracle Text Preferences" skip 2
 
 
COLUMN pre_owner  format a15 heading "Owner" 
COLUMN pre_name   format a35 heading "Parameter" 
COLUMN pre_class  format a15 heading "Class" 
COLUMN pre_object format a35 heading "Object" 
 
SELECT 	 pre_owner
	   , pre_name
       , pre_class
       , pre_object
  FROM ctxsys.ctx_preferences 
 WHERE UPPER(pre_owner) IN (UPPER('&&USER_NAME.'))
ORDER BY 1,2,3
/
 
ttitle LEFT  "Oracle Text Attributes" skip 2
 
COLUMN prv_owner      format a15 heading "Owner" 
COLUMN prv_preference format a30 heading "Perference" 
COLUMN  prv_attribute format a20 heading "Attribute" 
COLUMN prv_value      format a50 heading "Value" 
 
SELECT prv_owner
	,  prv_preference
	,  prv_attribute
	,  prv_value 
 FROM  ctxsys.ctx_preference_values 
 WHERE UPPER(prv_owner) IN (UPPER('&&USER_NAME.'))
ORDER BY 1,2,3,4
/ 
 
ttitle off

Aktuellste Version siehe hier https://orapowershell.codeplex.com/SourceControl/latest#sql/ctx.sql


Quellen

Themen Sammlung

Cookies helfen bei der Bereitstellung von Inhalten. Durch die Nutzung dieser Seiten erklären Sie sich damit einverstanden, dass Cookies auf Ihrem Rechner gespeichert werden. Weitere Information
"Autor: Gunther Pipperr"
dba/oracle_text.txt · Zuletzt geändert: 2017/03/22 15:31 von Gunther Pippèrr