Как выполнить полнотекстовый поиск CTXSYS.CONTEXT в таблице, к которой я обращаюсь через ссылку на базу данных Oracle?

У меня есть схема, содержащая синоним таблицы, связанной ссылкой с базой данных (поскольку другая схема имеет другой SID). Таблица содержит индекс CTX.CONTEXT. Когда я пытаюсь выполнить запрос, подобный следующему

select * from my_table c 
    where CTXSYS.CONTAINS(c.index_col, ' [ {ant} ]  ', 1) > 0 

Я получаю эту ошибку:

ORA-20000: Oracle Text error:
DRG-10599: column is not indexed

Однако, если я запускаю тот же запрос в схеме таблицы, я получаю результаты. Оказывается, CTXSYS.CONTAINS нельзя вызвать через ссылку на базу данных. Как выполнить полнотекстовый поиск по синониму?


person dougd_in_nc    schedule 06.01.2015    source источник


Ответы (1)


Я искал ответ во многих местах. В одном сообщении предлагалось создать функцию, которая получала бы оценку CONTEXT для строки и возвращала бы ее. Однако это медленно, так как функция выполняет запрос один раз для каждой строки.

Итак, я создал следующий пакет, который запускает поиск один раз, а затем кэширует результаты, что делает получение результатов очень быстрым.

create or replace
PACKAGE SEARCH_PKG AS
  TYPE t_scores IS TABLE OF NUMBER INDEX BY pls_integer;
  TYPE t_scores_by_search IS TABLE of t_scores INDEX BY VARCHAR2(1000);
  TYPE t_searches_done IS TABLE of BOOLEAN INDEX BY VARCHAR2(1000);

  FUNCTION search(i_unique_id NUMBER, i_text VARCHAR2) RETURN NUMBER;

END;
/

create or replace
PACKAGE BODY SEARCH_PKG AS

  search_scores t_scores_by_search;
  searches_done t_searches_done;

  FUNCTION search(i_unique_id NUMBER, i_text VARCHAR2) RETURN NUMBER
  IS
  BEGIN   

    IF searches_done.exists(i_text) = FALSE THEN
      FOR c1 IN (SELECT score(1) text_score, my_table_id FROM my_table WHERE contains(index_col, i_text, 1) > 0)
      LOOP
        search_scores(i_text)(c1.my_table_id) := c1.text_score;
      END LOOP;
    END IF;

    searches_done(i_text) := TRUE;

    IF search_scores.exists(i_text) AND search_scores(i_text).exists(i_unique_id)  THEN
      RETURN search_scores(i_text)(i_unique_id);
    ELSE
      RETURN 0;
    END IF;
  END;
END SEARCH_PKG;
/

Затем вы можете запустить запрос, подобный следующему, чтобы выполнить полнотекстовый поиск:

SELECT * FROM my_table WHERE search_pkg.search(my_table_id, ' [ {ant} ]  ') > 0 

Обратите внимание, что для каждого другого поиска, который вы выполняете, сохраняется больше данных. Итак, если у вас есть длительные соединения, вы можете захотеть сделать в пакете еще одну процедуру для очистки структур данных.

person dougd_in_nc    schedule 06.01.2015