Benutzer-Werkzeuge

Webseiten-Werkzeuge


prog:oracle_text_contains

Unterschiede

Hier werden die Unterschiede zwischen zwei Versionen angezeigt.

Link zu dieser Vergleichsansicht

Beide Seiten der vorigen RevisionVorhergehende Überarbeitung
prog:oracle_text_contains [2017/04/22 16:11] – [Oracle Text - In Texten suchen] gpipperrprog:oracle_text_contains [2023/11/08 14:11] (aktuell) – [Oracle Text - In Texten suchen] gpipperr
Zeile 1: Zeile 1:
 +=====Oracle Text - In Texten suchen=====
 +
 +Einführung in Oracle Text => [[dba:oracle_text|Oracle Text - Volltext Suche über Text Dokumente]]
 +
 +Nach der Indizierung der Daten kann nun in den Daten gesucht werden. Für die Suche steht der CONTAINS Operator zur Verfügung.
 +
 +{{:prog:apex:apex_katze_v04.png?direct&200 | Oracle Text Katze V3}}
 +
 +
 +Syntax:
 +<code sql>
 +SELECT id
 +     , SCORE(1) 
 +  FROM TEXTE
 + WHERE CONTAINS(column, 'query_string',1)>0
 +/
 +</code>
 +
 +Mit der SCORE Funktion (die Nummer 1 ist hier die gleiche Nummer wie der dritte CONTAINS Parameter) kann die Relevanz eines Treffers angezeigt werden.
 +
 +
 +Hier wurde das von Oracle auch mal beschrieben => (Salton's formula) [[https://docs.oracle.com/database/121/CCREF/ascore.htm#CCREF1475|Scoring Algorithm for Word Queries Oracle 12c]]
 +
 +
 +Der Score ist die [[https://en.wikipedia.org/wiki/Tf%E2%80%93idf|term frequency–inverse document frequency]] im Verhältnis von 1 bis 100.
 +
 +
 +Ab Oracle 11 kann das Scoring verhalten beeinflusst werden:
 +
 +<code sql>
 +DISCRETE     Term vorhanden 100, falls nicht 0
 +OCCURRENCE   Anzahl der Vorkommen
 +RELEVANCE    Standard-Relevanz-Ranking
 +COMPLETION   Ratio für Section Suche: Anzahl der der Treffer zu Anzahl aller Ausdrücke
 +IGNORE       Scoring des Terms ignorieren
 +LOG,ABS und Rechenoperationen () für Gruppierung
 +
 +wie:
 +
 +SELECT id
 +     , SCORE(1) 
 +  FROM TEXTE
 + WHERE CONTAINS(column, 'DEFINESCORE(query_string, DISCRETE)',1)>0
 +/
 +
 +</code>
 +
 +siehe auch => https://docs.oracle.com/en/database/oracle/oracle-database/23/ccref/oracle-text-CONTAINS-query-operators.html
 +
 +
 +
 +==== Test Daten anlegen ====
 +
 +Im ersten Schritt legen wir einen Beispiel Text an um die wichtigsten Suchfunktionen zu erklären:
 +
 +
 +Anlegen der Beispieldaten und indizieren:
 +<code sql>
 +-- as sys 
 +-- grant rights to create the index
 +connect sys as sysdba
 +
 +grant CTXAPP to gpi
 +
 +connect gpi/gpi
 +
 +create table texte ( id number(11) primary key, text varchar2(4000));
 +insert into texte values (1,'Ein Hund steht neben der Hütte');
 +insert into texte values (2,'Die liebsten Haustiere sind Katze und Hund');
 +insert into texte values (3,'Die Katze auf dem Dach');
 +commit;
 +
 +
 +-- Index Properties for the lexer
 +-- exec ctx_ddl.drop_preference( 'gpi_lexer');
 +
 +begin
 +ctx_ddl.create_preference( 'gpi_lexer', 'BASIC_LEXER' );
 +ctx_ddl.set_attribute ('gpi_lexer', 'INDEX_THEMES', 'YES');
 +-- nur 12c?
 +ctx_ddl.set_attribute ('gpi_lexer', 'INDEX_STEMS', 'GERMAN_NEW');
 +-- 10/11
 +--ctx_ddl.set_attribute ('gpi_lexer', 'INDEX_STEMS', 'GERMAN');
 +end;
 +/
 +
 +
 +--Section group
 +-- exec CTX_DDL.DROP_SECTION_GROUP('gpi_section');
 +
 +begin
 +ctx_ddl.create_section_group ('gpi_section', 'NULL_SECTION_GROUP');
 +ctx_ddl.add_special_section ('gpi_section', 'SENTENCE');
 +ctx_ddl.add_special_section ('gpi_section', 'PARAGRAPH');
 +end;
 +/
 +
 +
 +-- create the index
 +-- drop index idx_texte ;
 +
 +CREATE INDEX idx_texte ON texte(text)  
 +             INDEXTYPE IS CTXSYS.CONTEXT 
 +             PARAMETERS ('LEXER gpi_lexer SECTION GROUP gpi_section')
 +/
 +
 +------------------
 +-- check for errors
 +SELECT count(*) FROM ctx_user_index_errors
 +/
 +
 +</code>
 +
 +Unsere Daten sehen dann so aus:
 +{{ :dba:oracle_text:oracle_text_contains_operator_beispiele_v01.png?direct |Oracle Text Beispiel Daten}}
 +
 +
 +----
 +
 +====Exakte Wort-/Phrasensuche====
 +
 +Suche nach dem Wort in allen Texten:
 +<code sql>
 +select id,text from texte where contains(text, 'Hund')>0
 +</code>
 +
 +Ergebnis:
 +  * 1  Ein Hund steht neben der Hütte
 +  * 2  Die liebsten Haustiere sind Katze und Hund
 +
 +
 +----
 +
 +====Logische Kombinationen “AND &”, “OR | ”, “NOT ====
 +
 +Über die logischen Operatoren können Kombinationen von Wörtern gesucht werden.
 +<code sql>
 +select * from texte where contains(text,'Hund AND Katze')>0;
 +select * from texte where contains(text,'Hund & Katze')>0;
 +</code>
 +
 +Ergebnis:
 +  * 2 Die liebsten Haustiere sind Katze und Hund 
 +
 +
 +Die Suche nach dem Wort "AND" ist dann allerdings nicht mehr möglich, ist quasi ein reserviertes Wort ( Fehler : DRG-50901: text query parser syntax error ).
 +
 +
 +----
 +
 +====Wildcard-Suche====
 +
 +Mit _ nach einem beliebigen Zeichen, mit % nach beliebig vielen Zeichen suchen:
 +<code sql>
 +select * from texte where contains(text, ‘Hu%d AND Hüt_e’) >0;
 +</code>
 +
 +Ergebnis:
 +  * 1 Ein Hund steht neben der Hütte
 +
 +Wird viel am Anfang oder am Ende eines einzelnen Wortes mit einem Wildcard gesucht, lohnt es sich den Index um die Eigenschaft "prefix index" (eine eigene Index Tabelle mit allen möglichen Wortfragmenten bis zu einer definierten Anzahl von Buchstaben) zu erweitern um die Performance bei der Suche zu verbessern.
 +
 +----
 +
 +====Soundex - ! ====
 +
 +Nach einer ähnlichen Aussprache eines Wortes suchen, funktioniert am besten mit US Englisch in 7 Bit Darstellung, kann aber auch recht gute Ergebnisse mit europäischen Sprachen in 8Bit Darstellung erreichen.
 +
 +<code sql>
 +select * from texte where contains(text, '!Haustire’ )>0;
 +</code>
 +
 +Ergebnis:
 +  * 2 Die liebsten Haustiere sind Katze und Hund
 +
 +Vermutlich wird hier auf den klassischen [[dba:oracle_soundex_function|Mit Soundex Wörter in der Datenbank vergleichen]] Algorithmus zurückgegriffen.
 +
 +
 +----
 +
 +====Fuzzy matching - ? ====
 +
 +Der Fuzzy matching Algorithmus ist deutlich mächtiger als der statische Soundex Algorithmus, wertet aber auch die ähnliche Aussprache von Wörtern aus.
 +
 +Es kann der **?** Operator oder für mehr Parameter **fuzzy(term, score, numresults, weight)** verwendet werden.
 +
 +<code sql>
 +-- Short Version
 +select * from texte where contains(text, '?Hunt') >0;
 +-- Details Version
 +select * from texte where contains(text, 'fuzzy(Hunt, 50, 50, WEIGHT)') >0;
 +</code>
 +
 +Ergebnis:
 +  * 1  Ein Hund steht neben der Hütte
 +  * 2  Die liebsten Haustiere sind Katze und Hund
 +
 +
 +----
 +
 +====Multilinguale Stammsuche - $ ====
 +
 +Mit der stem ($) Suche wird nach Wörtern mit der gleichen linguistischen Wurzel gesucht, in unsere Beispiel suchen wir nach "stehen" der  Basis von "steht".
 +
 +Der Oracle Text Stemmer basiert auf der Lösung von XSoft Division of Xerox Corporation und unterstütze mit dem BASIC_LEXER: Englisch, Französisch, Spanisch, Italienisch, Deutsch und Dänisch. 
 +
 +Aufruf:
 +<code sql>
 +select * from texte where contains(text, '$stehen' )>0
 +</code>
 +
 +Das erwartete Ergebnis:
 +  * 1  Ein Hund steht neben der Hütte
 +
 +
 +Damit das funkioniert muss aber diese Eigenschaft vor dem anlegen des Indexes definiert werden: EXEC ctx_ddl.set_attribute ('gpi_lexer', 'INDEX_STEMS', 'GERMAN');
 +
 +
 +Das Dicitonary für zum Beispiel Deutsch liegt hier: $ORACLE_HOME/ctx/data/delx/drde.dct und fehlt unter der Oracle XE Edition .-), daher funktioniert das auf Deutsch bei der Oracle XE auch nicht....
 +
 +
 +----
 +====Near – Operator ====
 +
 +Mit Near wird ein Score bzgl. des Abstands von zwei Wörtern in einen Text ermittelt.
 +
 +Suche in der Nähe der Begriffe mit einem Radius von 2:
 +<code sql>
 +select * from  tab where contains(text, 'near((Hund, Katze), 2)' )>0
 +</code>
 +
 +Ergebnis:
 +  * 2 Die liebsten Haustiere sind Katze und Hund
 +
 +
 +
 +----
 +====Suche in Sektionen, Sätzen und Paragraphen - WITHIN====
 +
 +Suche in Abschnitten wie ein Satz:
 +<code sql>
 +select * from texte where contains(text,'(Hund, Katze) WITHIN SENTENCE') >0
 +</code>
 +
 +Ergebnis: Alle 3 Zeilen
 +
 +
 +
 +<fc #800000>Fehler: DRG-10837: section SENTENCE does not exist</fc>
 +
 +Der Index muss natürlich auch entsprechend so aufgebaut werden, das Abschnitte erkannt werden können.
 +Stichwort Section Group, siehe die beim Indexaufbau verwendeten Einstellungen.
 +
 +
 +----
 +
 +====Themen bezogene (Themes) Suche - about ====
 +<code sql>
 +select * from  texte where contains(text, 'about(Hund)' )>0
 +</code>
 +
 +Ergebnis:
 +  * 1 Ein Hund steht neben der Hütte
 +  * 2 Die liebsten Haustiere sind Katze und Hund
 +
 +Auch hier verläßt einen die XE Edition mit Deutsch, Fehler DRG-11422: linguistic initialization failed
 +DRG-11432: file error while accessing knowledge base, die passenden Dateien sind auf der Platte im Oracle Home nicht vorhanden.
 +
 +Bzgl. theme Index siehe auch: [[dba:oracle_text_index_themes|Einen Oracle Theme Index aufbauen]] und [[dba:oracle_text_thesaurus|Mit einem Thesaurus und Oracle Text arbeiten]]
 +
 +
 +----
 +
 +====Score bezogene Funktionen: accumulate, minus, weight====
 +
 +
 +<code sql>
 +select * from  texte where contains(text, 'Hund MINUS Katze') >0;
 +</code>
 +
 +Ergebnis:
 +  * 1 Ein Hund steht neben der Hütte
 +
 +<code sql>
 +select * from  texte where contains(text, 'Hund OR Katze *2') >0;
 +</code>
 +
 +Ergebniss: Alle Zeilen in der Tabelle werden gefunden
 +
 +
 +----
 +
 +====Operationen auf Ergebnislisten: threshold (nur ab dem Score====
 +
 +<code sql>
 +select * from texte where contains(text, 'Hund > 3,5')>0
 +</code>
 +
 +Ergebnis:
 +  * 1 Ein Hund steht neben der Hütte
 +  * 2 Die liebsten Haustiere sind Katze und Hund
 +
 +----
 +
 +====ISO 2788  konformer Thesaurus - SYN, NT, BT ====
 +
 +<code sql>
 +select * from texte where contains(text, 'SYN(Hund,TIERE)') >0
 +</code>
 +
 +Der Thesaurus muss zuvor definiert werden, ansonsten wird die Fehlermeldung "DRG-11702: thesaurus TIERE does not exist" aufgerufen.
 +
 +Ein Thesaurus  kann auch direkt abgefragt werden mit CTX_THES.<REGEL> wie :
 +<code sql>
 +select CTX_THES.SYN('automobile','t_fahrzeuge') AS SYN from dual;
 +</code>
 +siehe dazu [[dba:oracle_text_thesaurus|Mit einem Thesaurus und Oracle Text arbeiten]]
 +
 +----
 +
 +==== Quellen ====
 +
 +Doku:
 +  * https://docs.oracle.com/database/121/CCREF/cqoper.htm#CCREF0300
 +