Vor nun schon fast vier Jahren hatten wir bereits ein Blog-Posting zum Thema
"Treffer zählen mit Oracle TEXT" veröffentlicht. Zusammengefasst kann man
sagen, dass man nach Möglichkeit immer mit CTX_QUERY.COUNT_HITS arbeiten
sollte. Diese Prozedur stellt sicher, dass die Zählung ausschließlich im Textindex stattfindet und
dass (teure) Zugriff auf die Basistabelle unterbleiben.
set serveroutput on declare v_number number; begin v_number := ctx_query.count_hits( index_name => 'MY_FULLTEXT_IDX', text_query => 'oracle and text', exact => true ); dbms_output.put_line('Anzahl Treffer: '||v_number); end; / Anzahl Treffer: 2657
Doch was ist, wenn der Oracle Textindex mit dem in Oracle11g neuen Feature
Composite Domain Index erstellt wird ...?
CREATE INDEX comp_ind ON customers(cust_first_name) INDEXTYPE IS ctxsys.context FILTER BY cust_id, cust_year_of_birth ORDER BY cust_year_of_birth
Der Composite Domain Index nimmt die in der FILTER BY-Klausel angegebenen Spalten mit
in den Volltextindex auf und führt mixed Queries wie die folgende dann allein
mit Hilfe des Oracle TEXT Index aus.
SELECT cust_id FROM customers WHERE contains (cust_first_name, 'A% or D% or N% or B%') > 0 AND cust_year_of_birth > 1970 /
Wenn nun die Treffer gezählt werden sollen, tut man sich bei der Nutzung von
CTX_QUERY.COUNT_HITS etwas schwer ... denn wo soll man das Filterkriterium
cust_year_of_birth > 1970 einsetzen ...?
FUNCTION COUNT_HITS RETURNS NUMBER Argument Name Typ In/Out Defaultwert? ------------------------------ ----------------------- ------ -------- INDEX_NAME VARCHAR2 IN TEXT_QUERY VARCHAR2 IN EXACT BOOLEAN IN DEFAULT PART_NAME VARCHAR2 IN DEFAULT
Die Lösung ist einfacher, als man denkt: Denn für jede der in der FILTER BY-Klausel
angegebenen Spalten bildet Oracle TEXT eine
SDATA-Section gleichen Namens. In diesem Fall haben wir
also die SDATA Sections CUST_YEAR_OF_BIRTH und CUST_ID. Und diese
lässt sich nun auch als Teil der CONTAINS-Abfrage explizit ansprechen. Die
CONTAINS-Abfrage mit SDATA-Section sieht dann so aus ...
'A% or D% or N% or B% and SDATA(cust_year_of_birth > 1970)
Eingesetzt in CTX_QUERY.COUNT_HITS ...
set serveroutput on declare v_number number; begin v_number := ctx_query.count_hits( index_name => 'COMP_IND', text_query => 'A% or D% or N% or B% and SDATA(cust_year_of_birth > 1970)', exact => true ); dbms_output.put_line('Anzahl Treffer: '||v_number); end; / Anzahl Treffer: 1623
Mehr Information in der Oracle Dokumentation - TEXT Reference.