Donnerstag, 17. April 2008

Ein Einstieg in Oracle TEXT ...

Oracle TEXT ist eine in die Datenbank integrierte Volltextrecherche, die in allen Datenbankeditionen enthalten ist (kostet also nichts extra) und normalerweise ohne weitere Installation direkt zur Verfügung steht. Man kann in einem "normalen" Datenbankschema also sofort starten. Und da die meisten Oracle-Anwender oder Entwickler Oracle TEXT noch nicht kennen, wollen wir nun genau dies tun:
Das folgende SQL-Skript erzeugt eine Tabelle, fügt ein paar (kleine) "Dokumente" ein, erzeugt den Volltextindex und zeigt, wie man darin (sogar linguistisch) suchen kann ...
Zunächst: Tabelle anlegen und füllen - als "Dokumente" haben wir ein paar "Schlagzeilen" generiert ...
drop table texttabelle
/
drop sequence seq_texttabelle
/

create table texttabelle(
  id          number(10),
  dokument    clob
)
/

create sequence seq_texttabelle
/

insert into texttabelle values (seq_texttabelle.nextval, 'A-Partei gewinnt Wahl in Hansestadt');
insert into texttabelle values (seq_texttabelle.nextval, 'Terror in Nahost: Kriminalität steigt immer weiter an');
insert into texttabelle values (seq_texttabelle.nextval, 'Wirtschaft: Erneuter Gewinnzuwachs in diesem Jahr');
insert into texttabelle values (seq_texttabelle.nextval, 'Olympia rückt näher: Der Fackellauf ist in vollem Gange');
insert into texttabelle values (seq_texttabelle.nextval, 'Wer wird US-Präsident? Obama und Clinton machen Wahlkampf');
insert into texttabelle values (seq_texttabelle.nextval, 'Papst bestürzt über jüngsten Skandal!');
insert into texttabelle values (seq_texttabelle.nextval, 'Wahlkampf in den USA geht weiter:  Clinton und Obama LIVE zu sehen');
insert into texttabelle values (seq_texttabelle.nextval, 'Software-Kenntnisse werden immer wichtiger');
insert into texttabelle values (seq_texttabelle.nextval, 'Umfrage:  Alle wollen mehr Geld!');
insert into texttabelle values (seq_texttabelle.nextval, 'Der Papst liest seine erste Messe in den USA!');

commit
/
Nun wird der Index erzeugt ...
create index idx_text on texttabelle (dokument)
indextype is ctxsys.context
/
Fertig. Nun kann man suchen ... und das geht wie folgt:
  1. Die einfachste Variante: Suche nach einem Wort:
    SQL> select * from texttabelle where contains(dokument, 'Papst')>0;
    
            ID DOKUMENT
    ---------- ---------------------------------------------------------------
             6 Papst bestürzt über jüngsten Skandal!
            10 Der Papst liest seine erste Messe in den USA!
    
    2 Zeilen ausgewählt.
    
  2. Boole'sche Operatoren wie AND, OR, NOT gehen natürlich auch ...
    SQL> select * from texttabelle where contains(dokument, 'Papst and Skandal')>0;
    
            ID DOKUMENT
    ---------- ---------------------------------------------------------------------------
             6 Papst bestürzt über jüngsten Skandal!
    
    1 Zeile wurde ausgewählt.
    
  3. Nun wird's interessant: Wir suchen Dokumente, in denen jemand etwas "liest" ... und das kann sprachlich ja unterschiedlich aussehen ... (lesen, las, liest, gelesen, ...). Dazu gibt es in Oracle TEXT eine Wortstammsuche ...
    SQL> select * from texttabelle where contains(dokument, '$lesen')>0;
    
            ID DOKUMENT
    ---------- ------------------------------------------------------------------------
            10  Der Papst liest seine erste Messe in den USA!
    
    1 Zeile wurde ausgewählt.
    
  4. Oracle TEXT ist übrigens auch noch fehlertolerant ... wenn man den Fuzzy-Operator verwendet ... Suchen wir mal nach dem USA-"Wahlkrampf":
    SQL> select * from texttabelle where contains(dokument, '?Wahlkrampf')>0;
    
            ID DOKUMENT
    ---------- ------------------------------------------------------------------------
             5 Wer wird US-Präsident? Obama und Clinton machen Wahlkampf 
             7 Wahlkampf in den USA geht weiter:  Clinton und Obama ...
    
    2 Zeilen ausgewählt.
    
  5. Ein (vorerst) letztes Beispiel: Zwei Wörter sollen nah beeinander stehen ("nah" meint hier: es darf nur ein Wort dazwischen stehen):
    SQL> select * from texttabelle 
      2   where contains(dokument, 'NEAR((Clinton, Wahlkampf),2)')>0;
    
            ID DOKUMENT
    ---------- --------------------------------------------------------------------------------
             5 Wer wird US-Präsident? Obama und Clinton machen Wahlkampf 
    
    1 Zeile wurde ausgewählt.
    
Am besten probiert man es einfach mal aus ... mehr zum Thema kommt in Kürze ...

Kommentare:

Robert hat gesagt…

Danke!. Beim Ausporbieren ist mir aufgefallen, dass die Suche nach $lesen kein Ergebnis brachte. Alle anderen Abfragen waren richtig.

Gruß
RJ

Carsten Czarski hat gesagt…

Hallo Robert,

das liegt wahrscheinlich daran, dass alle Defaults in der Datenbank auf Englisch stehen. Dann versucht der Stemmer ebenfalls, mit Englisch zu arbeiten. Eine lösung hierfür wäre das Setzen des "stemmer" attributs auf "german" in der "Wordlist Preference"; mehr Info hier:

http://docs.oracle.com/cd/E11882_01/text.112/e24436/cdatadic.htm#CCREF2023

Max Stadler hat gesagt…

Hallo Carsten,

danke für die super Anleitung.

Wir haben den Stemmer wie von dir im Link angegeben, auf Deutsch gesetzt. Doch leider ergab unsere Wortstammsuche keinen Treffer.

Den Index haben wir anschließend neu erstellt und wir verwenden die Daten deines Beispieles.
Zusätzlich ist zu erwähnen, dass wir mit der Oracle 11 XE arbeiten.

Hast du vielleicht noch einen Tipp für uns woran das liegen könnte?

Gruß
Max

Carsten Czarski hat gesagt…

Hallo Max,

hmmm ... kannst Du mir mal eure Kommandos zusenden ...? Dann kann ich sicherlich mehr dazu sagen. Am besten offline via email: carsten[dot]czarski(at)oracle}dot{com.

Beste Grüße

Carsten

radfahrer hat gesagt…

Ich habe einen Index auf den Spalten Vorname und Nachname in einem User Datastore.

Der Index wird mit Standardeinstellungen erzeugt.

Die meisten Querys funktionieren schnell und gut.

Nur wenn ich - zur Simulation eines Tippfehlers - in einer Query den ersten Vokal weglasse, dann findet Oracle Text nichts. Weder genau noch Fuzzy. Als gäbe es den Namen nicht.

Beispiel:

Ich finde 12 Ergebnisse für Wolfgang Fischer, aber kein einziges für Wolfgang Fscher (jeweils mit "{Wolfgang} within Vorname and {Fischer} within Nachname" und éntsprechend mit fuzzy(...,60,50,w) in der zweiten Relaxation.

Wie kann ich Oracle Text einstellen, so dass auch bei einem fehlenden ersten Vokal Treffer erzielt werden?

Danke, Wolfram

Carsten Czarski hat gesagt…

Hallo Wolfram,

die Arbeitsweise des Fuzzy-Algorithmus hat natürlich Grenzen - bestimmte Dinge werden einfach nicht mehr gefunden - das sind die, die der Algorithmus zur Feststellung der Ähnlichkeit braucht (der erste Vokal spielt hier schon eine Rolle). Als Alternative könntest Du Dir mal das Name Search Feature ansehen. Dazu gibt es zwei Blog Postings:

http://oracle-text-de.blogspot.co.uk/2010/09/neues-oracle-text-feature-name-search.html

http://oracle-text-de.blogspot.co.uk/2011/05/unscharfe-namenssuche-name-search-mit.html

Beste Grüße

Carsten

radfahrer hat gesagt…

Carsten, vielen Dank für die Antwort.

Dass der erste Vokal ein besondere Rolle spielt hatten wir auch schon vermutet, die Symptome sind da sehr klar.

Name Search liefert wirklich unglaubliches, aber versagt leider an dieser Stelle ebenso; es gibt jede Menge ganz entfernt ähnlicher Treffer, aber kein "Wlfram" oder kein "Fscher" ist dort im Resultat vorhanden.

Das werden wir den Anwendern dann wohl ganz vorsichtig erklären müssen - die bisherige Lösung konnte das noch.

Carsten Czarski hat gesagt…

Hallo Wolfram,

eine Möglichkeit wäre noch, die Fuzzy-Suche mit einer Wildcard Suche (%scher) zu kombinieren. Für die Wildcard Suche mit Wildcard links müsste der "Substring-Index" (Nicht zu verwechseln mit dem "Prefix Index") eingeschaltet werden. Dazu mehr hier: http://docs.oracle.com/database/121/CCREF/cdatadic.htm#CCREF2023.

Wenn man zusätzlich Query Relaxation verwendet, kann man sicherstellen, dass die Wildcard-Suche erst dann einsetzt, wenn per Fuzzy nicht genug gefunden wird. Mehr dazu hier: http://oracle-text-de.blogspot.com/2009/01/viele-abfragen-auf-einmal-query.html.

Hilft dies weiter?

Beste Grüße

Carsten

Klaus hat gesagt…

Hallo, auch von mir vielen Dank für die informative Anleitung!

Kleine Rückfragen zum Thema Nachinstallation von Oracle Text:

Ist es ebenso gut möglich diese mittels des Scripts (aus dbca Scripts in .sql)

/opt/app/oracle/admin/cdba/scripts/context.sql

auszuführen? Und hat sich diesbezüglich von Oracle Version 11.2 nach 12.1 etwas geändert?

Mit freundlichen Grüßen

Klaus

Carsten Czarski hat gesagt…

Hallo Klaus,

es gibt eine MyOracle-Support Note (970473.1) welche die manuelle Installation von Oracle TEXT beschreibt - es läuft auf das Skript $ORACLE_HOME/ctx/admin/catctx.sql hinaus.

Beste Grüße

Carsten

Beliebte Postings