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.