Benutzer-Werkzeuge

Webseiten-Werkzeuge


prog:oracle_text_highlight

Unterschiede

Hier werden die Unterschiede zwischen zwei Versionen angezeigt.

Link zu dieser Vergleichsansicht

Beide Seiten der vorigen RevisionVorhergehende Überarbeitung
Nächste Überarbeitung
Vorhergehende Überarbeitung
prog:oracle_text_highlight [2016/04/24 21:48] – [Oracle Text - Die Treffer einer Oracle Volltext Abfrage in der Ergebnismenge optisch hervorheben] gpipperrprog:oracle_text_highlight [2016/05/11 19:41] (aktuell) – [Oracle 12c New Feature - Forward Indexing] gpipperr
Zeile 1: Zeile 1:
 +=====Oracle Text - Die Treffer einer Oracle Volltext Abfrage in der Ergebnismenge optisch hervorheben====
 +
 +**Ab 10g/11g/12c**
 +
 +
 +Einführung in Oracle Text => [[dba:oracle_text|Oracle Text - Volltext Suche über Text Dokumente]]
 +
 +Nach dem ein Dokument mit einer Volltext Suche gefunden wurde, stellt sich natürlich die Frage, wo denn im Text etwas erkannt wurde.
 +
 +Für die Aufbereitung der Trefferliste/Dokumentanzeige wird dazu das [[https://docs.oracle.com/database/121/CCREF/cdocpkg.htm#CCREF0700|CTX_DOC Package]] eingesetzt.
 +
 +
 +Für einzelne Textabschnitt kann mit "CTX_DOC.HIGHLIGHT" die Offset Position dazu bestimmt werden, oder mit CTX_DOC.SNIPPET ein Teil ausgeschnitten werden.
 +
 +Ab 12c kann mit Forward Indexing das ganze auch noch beschleunigt werden, allerdings wird dann auch mehr Speicherplatz in der Datenbank benötigt.
 +==== Teilbereiche aus dem Dokument mit dem gefundenen Wort hervorheben ====
 +
 +So kann zum Beispiel mit "CTX_DOC.SNIPPET" der Treffer Text Abschnitt angezeigt werden:
 +<code sql>
 +
 +--Session so setzen wie die Spalte in der Tabelle gefunden werden soll
 +--Fehlt das, siehe folgender Fehler
 +
 +exec ctx_doc.set_key_type('ROWID');
 +
 +-- Abfragen und Ergebniss mit ermitteln
 +
 +select CTX_DOC.SNIPPET(
 + index_name => 'IDX_DOC_FILES'
 + ,textkey    => rowid
 + ,text_query => '?Hunt'
 + ,starttag   => '<span style="color:#034F84; background-color:#F7CAC9">' 
 + ,endtag     => '</span>'
 + ,separator  => '<b>...</b>') as textfragment 
 +from texte where  contains(text, '?Hunt') >0
 +/
 +</code>
 +
 +Leider klappt das dann nicht, weil im ersten Test das setzen von "ctx_doc.set_key_type('ROWID') " vergessen wurde!
 +<fc #800000>Der Fehler</fc>:
 +<code>
 +ERROR at line 1:
 +ORA-29903: error in executing ODCIIndexFetch() routine
 +ORA-20000: Oracle Text error:
 +DRG-50857: oracle error in drvdoc.get_rowid
 +ORA-01410: invalid ROWID
 +ORA-06512: at "CTXSYS.DRUE", line 160
 +ORA-06512: at "CTXSYS.CTX_DOC", line 2606
 +ORA-06512: at line 1
 +</code>
 +
 +Wird nur mit ID  auf die PK Spalte verwiesen erhalten wir den folgenden Fehler:
 +
 +<code sql>
 +ERROR at line 1:
 +ORA-20000: Oracle Text error:
 +DRG-10826: no document with the specified textkey is found
 +ORA-06512: at "CTXSYS.DRUE", line 160
 +ORA-06512: at "CTXSYS.CTX_DOC", line 2606
 +ORA-06512: at line 1
 +</code>
 +
 +Hier lag der Fehler im falschen CTX Index Namen, gab mehrere davon .-(.
 +
 +
 +===Wie muss das nun ohne Fehler aufgerufen werden?===
 +
 +
 +Der Parameter **"textkey"** kann entweder auf der RowID oder auf den Primary Key der Tabelle arbeiten.
 +
 +Ist der PK aus mehreren Werten zusammengesetzt, muss mit CTX_DOC.PKENCODE der entsprechende Schlüssel aufgebaut werden.
 +
 +Warum aber funktioniert das in den obigen Beispiel erst mal einfach nicht?
 +
 +**Lösungsmöglichkeiten:**
 +  * Überprüfen, ob auch der richtige Index referenziert wird, bei einem falschen Index wird dieser durchsucht aber der Key kann ja nicht passen (na hoffentlich!)
 +
 +  * Überprüfen, ob die richtige Methode für den Key Zugriff zuvor ausgewählt wurde
 +    * exec ctx_doc.set_key_type('PRIMARY_KEY') (Default!) bei textkey => <PK_SPALTE>
 +    * exec ctx_doc.set_key_type('ROWID') bei textkey    => rowid
 +
 +
 +----
 +
 +
 +
 +
 +
 +
 +
 +
 +==== Das ganze Dokument als Text mit Markierung anzeigen ====
 +
 +
 +Hilfsfunktion zum Anzeigen eines ganzen Dokumentes:
 +
 +<code sql>
 +create or replace function ctx_apex_markup ( p_pk  varchar2
 +                                           , p_queryString varchar2
 +    , p_index_name  varchar2
 +
 +return clob 
 +is 
 +    -- temporären Lob für das Ergebnis
 +    v_storage clob; 
 +begin 
 +     -- Wie soll der Parameter Text Key ausgewertet werden!
 +     ctx_doc.set_key_type('PRIMARY_KEY');        
 +
 +     -- Markup Funktion in Memory nützen
 +     ctx_doc.markup (index_name  => upper(p_index_name)
 +                     ,textkey    => p_pk
 +                     ,text_query => p_queryString
 +                     ,restab     => v_storage 
 +                     ,starttag   => '<span style="color:#034F84; background-color:#F7CAC9">' 
 +                     ,endtag     => '</span>');                            
 +
 +   return v_storage; 
 +
 +end ctx_apex_markup;
 +
 +</code>
 +Das Clob Dokument muss natürlich von der rufenden Umgebung auch verarbeitete werden können, ab 32K muss hier also noch etwas mehr getan werden.
 +
 +Möchte man die Starttag/endtag Parameter nicht angeben, kann auch mit dem Parameter "tagset => 'HTML_NAVIGATE'" gearbeitet werden.
 +
 +Bei kurzen Texten klappt das aber so ganz gut:
 +<code sql>
 +select ctx_apex_markup(
 +   p_index_name    => 'IDX_TEXTE'
 + , p_pk            => to_char(ID)
 + , p_queryString   => '?Hunt'
 + )
 + as text
 +from texte where  contains(text, '?Hunt') >0
 +/
 +</code>
 +
 +
 +----
 +
 +==== Oracle 12c New Feature - Forward Indexing ====
 +
 +Um das Higlighting, Snippet und das Markup zu beschleunigen wird beim Anlegen des Oracle Text Domain Indexes eine neue zusätzliche Tabelle eingeführt, die $O, ein Mapping auf die $I.
 +
 +Parameter setzen:
 +<code sql>
 +exec ctx_ddl.create_preference('GPI_STORAGE ', 'BASIC_STORAGE' )
 +
 +exec ctx_ddl.set_attribute    ('GPI_STORAGE ', 'FORWARD_INDEX', 'TRUE' )
 +exec ctx_ddl.set_attribute    ('GPI_STORAGE ', 'SAVE_COPY', 'PLAINTEXT' )
 +
 +</code>
 +
 +siehe auch [[dba:oracle_text_index_binary_data#oracle_12c_new_storage_feature_-_plain_text_in_d_speichern_-_forward_indexing_in_o_ablegen|Oracle Text für die Indizierung binärer Daten verwenden]]
 +
 +
 +<fc #800000>Leider gleich mal auf eine Bug gelaufen</fc>
 +
 +Cursor von CTX_DOC.SNIPPET werden nicht geschlossen -  ORA-01000: maximum open cursors exceeded
 +
 +Bug 20892798 : MANY CURSORS OPENED WHEN USING FORWARD INDEXING LEADING TO ORA-01000 ERROR 
 +
 +
 +Kein FIX öffentlich – Falls gleicher Fehler Auftritt erneuten Bug mit Prio eröffnen und Druck machen!
 +
 +
 +
 +
 +
 +----
 +
 +==== Quellen ====
 +
 +Oracle Doku:
 +
 +  * CTX_DOC Package => https://docs.oracle.com/database/121/CCREF/cdocpkg.htm
  
prog/oracle_text_highlight.txt · Zuletzt geändert: 2016/05/11 19:41 von gpipperr