Seit kurzem ist das erste Patchset für 11g Release 2 (11.2.0.2) erschienen. Das ist in der Tat
besonders für die Nutzer von Oracle TEXT wichtig, denn das Basisrelease 11.2.0.1 enthielt
keine neuen Funktionen für Oracle TEXT - die wurden nun mit dem Patchset eingeführt. Im einzelnen
sind das ...
- Name search - dieser werden wir uns heute widmen
- Entity extraction and identification
- Result Set Interface
Interessant ist daher auch die Dokumentation zu Oracle TEXT - diese wurde mit dem
Erscheinen des Patchset übrigens ebenfalls ausgetauscht.
Doch heute mehr zum Thema Name Search. Diese neue Funktion in Oracle TEXT ist speziell
für die Suche nach Namen vorgesehen. Namen werden ja, insbesondere wenn Sie aus einem anderen Sprachraum kommen, recht häufig falsch geschrieben oder falsch verstanden. Man wendet die Rechtschreibregeln, die man kennt (hierzulande Deutsch) auf den fremden Namen an. Und das resultiert dann in einer völlig anderen Schreibweise. Eine exakte Suche hilft oft nicht weiter. Mit der
FUZZY-Suche kann man zwar schon nach ähnlich geschriebenen Begriffen suchen, für eine umfassende Suche nach Namen
reicht das jedoch vielfach nicht aus. Ich kenne das selbst recht gut - und werde auch meinen Namen "Czarski" hernehmen, um die neue Funktionalität vorzustellen.
Damit Namen mit der neuen Name Search-Funktion durchsucht werden können, müssen Sie beim Indizieren
besonders behandelt werden - wie wir noch sehen werden, erfolgt die Zerlegung in Tokens etwas anders
als bei normalen Texten. Aus diesem Grunde müssen Sie durch eine SECTION_GROUP mit Hilfe von
XML-Tags vom Rest des Dokumentes abgegrenzt werden. Das kann in beispielsweise so aussehen ...
drop table names / create table names ( id number(10), name varchar2(200) ) / insert into names values (1, '<name>Max Mustermann</name>'); insert into names values (2, '<name>Larry Ellison</name>'); insert into names values (3, '<name>Ulrike Schwinn</name>'); insert into names values (4, '<name>Carsten Czarski</name>'); insert into names values (5, '<name>Günther Stürner</name>');
Natürlich kann man auch Namen aus normalen, relationalen Tabellenspalten durchsuchbar machen. Diese indiziert
man dann
mit dem Multicolumn Datastore oder dem User Datastore. Wichtig ist, dass der Name in einem XML-Tag steht - das Tag selbst kann frei gewählt werden. Die Dokumentation zeigt im Abschnitt "Name Search" weiterführende Beispiele zur Namens-Indizierung von Tabellenspalten.
Die SECTION_GROUP für die Namen muss dann als NDATA-Section Group deklariert werden.
begin ctx_ddl.drop_section_group('name_sg'); end; / begin ctx_ddl.create_section_group('name_sg', 'BASIC_SECTION_GROUP'); ctx_ddl.add_ndata_section('name_sg', 'name', 'name'); end; /
Alles innerhalb des XML-Tags <name> gehört nun zur NDATA-Section und wird speziell für die Namenssuche
indiziert. Der nächste Schritt ist folgerichtig das Erstellen des Volltextindex.
create index ft_names on names (name) indextype is ctxsys.context parameters ('section group name_sg') /
Anschließend der erste spannende Moment - wir werfen mal einen Blick in die Tokentabelle ...
select token_type, token_text from dr$ft_names$i / TOKEN_TYPE TOKEN_TEXT ---------- ---------------------------------------------------------------- 200 ^arr 200 ^ars 200 ^ax$ 200 ^azi 200 ^bck 200 ^bec 200 ^bek 200 ^car 200 ^cas 200 ^chw : :
Das sieht ja schonmal etwas anders aus ... nun probieren wir das mal aus. Zunächst kann man
die Namen in beliebiger Reihenfolge suchen (schon mal nicht schlecht). Obwohl in der Tabelle
Carsten Czarski steht, kann ich nach Czarski, Carsten suchen ...
SQL> select * from names where contains(name, 'NDATA(name,Czarski\, Carsten)') > 0 ID NAME ---------- ---------------------------------------- 4Carsten Czarski 1 Zeile wurde ausgewählt.
Beachtet die Syntax: Eine Namenssuche wird durch den NDATA-Operator innerhalb der CONTAINS-Abfrage
eingeleitet. Der erste Parameter des NDATA-Operators ist wiederum die NDATA-Section-Group, also
das XML-Tag, in dem sich der Name befindet (hier: name). Es könnte ja sein, dass es
in XML-Dokumenten mehrere Namensabschnitte gibt. Danach kommt die Phrase, nach der gesucht wird und
danach kommen noch zwei Parameter: ORDER / NOORDER legt fest, ob die Reihenfolge der Namensbestandteile
berücksichtigt werden soll (NOORDER ist der Default) und PROXIMITY / NOPROXIMITY bestimmt, ob
die Ähnlichkeit des Suchbegriffs zum tatsächlichen Namen den Score beeinflussen soll.
Als nächstes habe ich ein paar Tests gemacht - mit dem Namen Czarski ist man ja einiges gewöhnt. Erstmal einfach ...
SQL> select * from names where contains(name, 'NDATA(name,zarsky)') > 0 ID NAME ---------- ---------------------------------------- 4Carsten Czarski 1 Zeile wurde ausgewählt.
Gut ... das hätte man mit dem FUZZY-Operator auch noch geschafft. Also noch etwas nachlegen ...
SQL> select * from names where contains(name, 'NDATA(name,Tsarski)') > 0 ID NAME ---------- ---------------------------------------- 4Carsten Czarski
Noch ein wenig ...
SQL> select * from names where contains(name, 'NDATA(name,Tscharski)') > 0 ID NAME ---------- ---------------------------------------- 4Carsten Czarski
Und ein letztes, weil's so schön ist ...
SQL> select * from names where contains(name, 'NDATA(name,Saarski Karsden)') > 0 ID NAME ---------- ---------------------------------------- 4Carsten Czarski
Das ist schonmal nicht schlecht - ein FUZZY-Operator hätte hier schon seine Grenzen gehabt ... Probieren wir
mal was anderes ... nicht ganz so exotisch und in Deutschland durchaus häufig anzutreffen.
SQL> select * from names where contains(name, 'NDATA(name,Schtürner)') > 0; ID NAME ---------- ---------------------------------------- 5Günther Stürner 1 Zeile wurde ausgewählt.
Auch das konnte ich mit FUZZY nicht hinbekommen. Die ersten Tests sind also recht ermutigend; ich
könnte mir vorstellen, dass dieses neue Feature nicht nur für die Volltextrecherche, sondern für viele
"ganz normale" Applikationen interessant ist, denn nach Namen sucht man häufig und vielfach hat man einen
Namen "nur gehört" und ist sich nicht sicher, wie er geschrieben ist. Es kann also durchaus sein, dass wir
in Zukunft öfter mal einen Oracle TEXT-Index auf einer ganz normalen Tabelle (mit Namensspalten) sehen werden.
Viel Spaß beim Ausprobieren!