=====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: --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 => '' ,endtag => '' ,separator => '...') as textfragment from texte where contains(text, '?Hunt') >0 / Leider klappt das dann nicht, weil im ersten Test das setzen von "ctx_doc.set_key_type('ROWID') " vergessen wurde! Der Fehler: 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 Wird nur mit ID auf die PK Spalte verwiesen erhalten wir den folgenden Fehler: 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 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 => * exec ctx_doc.set_key_type('ROWID') bei textkey => rowid ---- ==== Das ganze Dokument als Text mit Markierung anzeigen ==== Hilfsfunktion zum Anzeigen eines ganzen Dokumentes: 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 => '' ,endtag => ''); return v_storage; end ctx_apex_markup; / 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: 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 / ---- ==== 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: 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' ) 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]] Leider gleich mal auf eine Bug gelaufen 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