CTX_ANL в PL/SQL. Введение
Oracle Text — механизм полнотекстового поиска в Oracle Database.
Пакет CTX_ANL позволяет добавлять и удалять пользовательские словари для AUTO_LEXER,
чтобы учитывать отраслевую лексику, сокращения и новые слова.
Основные процедуры:
ADD_DICTIONARY(name, language, dictionary CLOB)— добавление словаря,DROP_DICTIONARY(name, language, dictionary CLOB)— удаление словаря.
Строки словаря разделяются переносами строк. Используются директивы:
STEM (корни слов), COMPOUND (сложные слова), части речи и признаки (род, склонение).
Ошибки формата выявляются при создании/изменении индекса (например, DRG-13710).
50 примеров использования CTX_ANL
Основные операции (1–10)
1. Создание преференса AUTO_LEXER
BEGIN
CTX_DDL.CREATE_PREFERENCE('a_lex','AUTO_LEXER');
END;
2. Добавление простого словаря
DECLARE
dict CLOB := 'STEM dog noun';
BEGIN
CTX_ANL.ADD_DICTIONARY('dict1','ENGLISH',dict);
END;
3. Удаление словаря
DECLARE
dict CLOB := 'STEM dog noun';
BEGIN
CTX_ANL.DROP_DICTIONARY('dict1','ENGLISH',dict);
END;
4. Добавление словаря с compound-словом
DECLARE
dict CLOB := 'COMPOUND help|desk STEM helpdesk noun';
BEGIN
CTX_ANL.ADD_DICTIONARY('dict2','ENGLISH',dict);
END;
5. Удаление compound-словаря
DECLARE
dict CLOB := 'COMPOUND help|desk STEM helpdesk noun';
BEGIN
CTX_ANL.DROP_DICTIONARY('dict2','ENGLISH',dict);
END;
6. Несколько STEM в словаре
DECLARE
dict CLOB := 'STEM cat noun' || CHR(10) || 'STEM cats nounPlural';
BEGIN
CTX_ANL.ADD_DICTIONARY('dict3','ENGLISH',dict);
END;
7. Удаление словаря с несколькими STEM
DECLARE
dict CLOB := 'STEM cat noun' || CHR(10) || 'STEM cats nounPlural';
BEGIN
CTX_ANL.DROP_DICTIONARY('dict3','ENGLISH',dict);
END;
8. Proper noun в словаре
DECLARE
dict CLOB := 'STEM Oracle nounProper';
BEGIN
CTX_ANL.ADD_DICTIONARY('dict4','ENGLISH',dict);
END;
9. Удаление словаря с proper noun
DECLARE
dict CLOB := 'STEM Oracle nounProper';
BEGIN
CTX_ANL.DROP_DICTIONARY('dict4','ENGLISH',dict);
END;
10. Признак рода в словаре
DECLARE
dict CLOB := 'STEM actor noun genderMasculine';
BEGIN
CTX_ANL.ADD_DICTIONARY('dict5','ENGLISH',dict);
END;
Морфология и признаки (11–20)
11. Женский род
DECLARE
dict CLOB := 'STEM actress noun genderFeminine';
BEGIN
CTX_ANL.ADD_DICTIONARY('dict6','ENGLISH',dict);
END;
12. Средний род
DECLARE
dict CLOB := 'STEM child noun genderNeuter';
BEGIN
CTX_ANL.ADD_DICTIONARY('dict7','ENGLISH',dict);
END;
13. Прилагательное
DECLARE
dict CLOB := 'STEM beautiful adjective';
BEGIN
CTX_ANL.ADD_DICTIONARY('dict8','ENGLISH',dict);
END;
14. Глагол
DECLARE
dict CLOB := 'STEM run verb';
BEGIN
CTX_ANL.ADD_DICTIONARY('dict9','ENGLISH',dict);
END;
15. Несколько частей речи
DECLARE
dict CLOB := 'STEM dance verb, noun';
BEGIN
CTX_ANL.ADD_DICTIONARY('dict10','ENGLISH',dict);
END;
16. Русский: declensionHard
DECLARE
dict CLOB := 'STEM стол noun declensionHard';
BEGIN
CTX_ANL.ADD_DICTIONARY('dict11','RUSSIAN',dict);
END;
17. Русский: declensionSoft
DECLARE
dict CLOB := 'STEM мать noun declensionSoft';
BEGIN
CTX_ANL.ADD_DICTIONARY('dict12','RUSSIAN',dict);
END;
18. Французский словарь
DECLARE
dict CLOB := 'STEM maison noun';
BEGIN
CTX_ANL.ADD_DICTIONARY('dict13','FRENCH',dict);
END;
19. Немецкий словарь
DECLARE
dict CLOB := 'STEM Haus noun';
BEGIN
CTX_ANL.ADD_DICTIONARY('dict14','GERMAN',dict);
END;
20. Русский словарь (простой STEM)
DECLARE
dict CLOB := 'STEM мир noun';
BEGIN
CTX_ANL.ADD_DICTIONARY('dict15','RUSSIAN',dict);
END;
Сложные конструкции (21–30)
21. Compound из трёх частей (EN)
DECLARE
dict CLOB := 'COMPOUND back|woods|man STEM backwoodsman noun';
BEGIN
CTX_ANL.ADD_DICTIONARY('dict16','ENGLISH',dict);
END;
22. Compound из четырёх частей (EN)
DECLARE
dict CLOB := 'COMPOUND mother|in|law|book STEM motherinlawbook noun';
BEGIN
CTX_ANL.ADD_DICTIONARY('dict17','ENGLISH',dict);
END;
23. Русский compound (пример)
DECLARE
dict CLOB := 'COMPOUND свет|форум STEM светофор noun';
BEGIN
CTX_ANL.ADD_DICTIONARY('dict18','RUSSIAN',dict);
END;
24. Немецкий compound (Biergarten)
DECLARE
dict CLOB := 'COMPOUND Bier|Garten STEM Biergarten noun';
BEGIN
CTX_ANL.ADD_DICTIONARY('dict19','GERMAN',dict);
END;
25. Французский compound (chef-d’œuvre)
DECLARE
dict CLOB := 'COMPOUND chef|d’|œuvre STEM chef-d’œuvre noun';
BEGIN
CTX_ANL.ADD_DICTIONARY('dict20','FRENCH',dict);
END;
26. Переопределение STEM
DECLARE
dict CLOB := 'STEM running verb';
BEGIN
CTX_ANL.ADD_DICTIONARY('dict21','ENGLISH',dict);
END;
27. STEM с proper noun (FR)
DECLARE
dict CLOB := 'STEM Paris nounProper';
BEGIN
CTX_ANL.ADD_DICTIONARY('dict22','FRENCH',dict);
END;
28. STEM + признаки (RU)
DECLARE
dict CLOB := 'STEM Москва nounProper genderFeminine';
BEGIN
CTX_ANL.ADD_DICTIONARY('dict23','RUSSIAN',dict);
END;
29. Несколько feature (EN)
DECLARE
dict CLOB := 'STEM student noun genderMasculine,declensionHard';
BEGIN
CTX_ANL.ADD_DICTIONARY('dict24','ENGLISH',dict);
END;
30. Несколько строк словаря
DECLARE
dict CLOB := 'STEM dog noun' || CHR(10) || 'STEM cat noun';
BEGIN
CTX_ANL.ADD_DICTIONARY('dict25','ENGLISH',dict);
END;
Массовые операции (31–40)
31. Генерация словаря из таблицы (LISTAGG)
DECLARE
dict CLOB;
BEGIN
SELECT LISTAGG('STEM ' || word || ' noun', CHR(10)) INTO dict
FROM my_words;
CTX_ANL.ADD_DICTIONARY('dict26','ENGLISH',dict);
END;
32. Удаление словаря, сформированного из таблицы
DECLARE
dict CLOB;
BEGIN
SELECT LISTAGG('STEM ' || word || ' noun', CHR(10)) INTO dict
FROM my_words;
CTX_ANL.DROP_DICTIONARY('dict26','ENGLISH',dict);
END;
33. Добавление словаря и проверка представления
DECLARE
dict CLOB := 'STEM demo noun';
BEGIN
CTX_ANL.ADD_DICTIONARY('dict27','ENGLISH',dict);
END;
-- Проверка
SELECT * FROM CTX_USER_ANALYZER_DICTS;34. Удаление словаря и проверка представления
DECLARE
dict CLOB := 'STEM demo noun';
BEGIN
CTX_ANL.DROP_DICTIONARY('dict27','ENGLISH',dict);
END;
-- Проверка
SELECT * FROM CTX_USER_ANALYZER_DICTS;35. Добавление словаря перед созданием индекса
DECLARE
dict CLOB := 'STEM document noun';
BEGIN
CTX_ANL.ADD_DICTIONARY('dict28','ENGLISH',dict);
END;
CREATE INDEX idx_docs ON docs(text) INDEXTYPE IS CTXSYS.CONTEXT;36. Удаление словаря перед перестроением индекса
DECLARE
dict CLOB := 'STEM document noun';
BEGIN
CTX_ANL.DROP_DICTIONARY('dict28','ENGLISH',dict);
END;
ALTER INDEX idx_docs REBUILD;37. Логирование ошибок добавления словаря
DECLARE
dict CLOB := 'WRONGFORMAT';
BEGIN
CTX_ANL.ADD_DICTIONARY('dict29','ENGLISH',dict);
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('Ошибка: ' || SQLERRM);
END;
38. Массовое добавление словарей в цикле
DECLARE
v_words SYS.ODCIVARCHAR2LIST := SYS.ODCIVARCHAR2LIST('alpha','beta','gamma');
dict CLOB;
BEGIN
FOR i IN 1..v_words.COUNT LOOP
dict := 'STEM ' || v_words(i) || ' noun';
CTX_ANL.ADD_DICTIONARY('dict' || i,'ENGLISH',dict);
END LOOP;
END;
39. Условное добавление (если нет в представлении)
DECLARE
dict CLOB := 'STEM test noun';
cnt NUMBER;
BEGIN
SELECT COUNT(*) INTO cnt FROM CTX_USER_ANALYZER_DICTS WHERE DICT_NAME='dict30';
IF cnt = 0 THEN
CTX_ANL.ADD_DICTIONARY('dict30','ENGLISH',dict);
END IF;
END;
40. Условное удаление (если найден в представлении)
DECLARE
dict CLOB := 'STEM test noun';
cnt NUMBER;
BEGIN
SELECT COUNT(*) INTO cnt FROM CTX_USER_ANALYZER_DICTS WHERE DICT_NAME='dict30';
IF cnt > 0 THEN
CTX_ANL.DROP_DICTIONARY('dict30','ENGLISH',dict);
END IF;
END;
Тестирование и сценарии (41–50)
41. Тест: есть ли токен после добавления
DECLARE
dict CLOB := 'STEM newword noun';
BEGIN
CTX_ANL.ADD_DICTIONARY('dict31','ENGLISH',dict);
END;
-- пример проверки (замени idx_docs на свой индекс):
SELECT token_text FROM dr$idx_docs$i WHERE token_text='newword';42. Перестроение индекса
ALTER INDEX idx_docs REBUILD;43. Русский глагол
DECLARE
dict CLOB := 'STEM читать verb';
BEGIN
CTX_ANL.ADD_DICTIONARY('dict32','RUSSIAN',dict);
END;
44. Немецкое сложное слово (Arbeitszeit)
DECLARE
dict CLOB := 'COMPOUND Arbeit|Zeit STEM Arbeitszeit noun';
BEGIN
CTX_ANL.ADD_DICTIONARY('dict33','GERMAN',dict);
END;
45. Удаление русского словаря
DECLARE
dict CLOB := 'STEM читать verb';
BEGIN
CTX_ANL.DROP_DICTIONARY('dict32','RUSSIAN',dict);
END;
46. Удаление немецкого словаря
DECLARE
dict CLOB := 'COMPOUND Arbeit|Zeit STEM Arbeitszeit noun';
BEGIN
CTX_ANL.DROP_DICTIONARY('dict33','GERMAN',dict);
END;
47. Валидация: намеренно некорректная строка
DECLARE
dict CLOB := 'STEM invalid';
BEGIN
CTX_ANL.ADD_DICTIONARY('dict34','ENGLISH',dict);
END;
-- Ошибка выявится при CREATE/ALTER INDEX (DRG-13710)48. Миграция: выгрузка словарей в другую схему
INSERT INTO other_schema.my_dicts
SELECT * FROM CTX_USER_ANALYZER_DICTS;49. Очистка всех словарей пользователя
DECLARE
CURSOR c IS SELECT DICT_NAME, LANGUAGE, DICTIONARY FROM CTX_USER_ANALYZER_DICTS;
BEGIN
FOR rec IN c LOOP
CTX_ANL.DROP_DICTIONARY(rec.DICT_NAME, rec.LANGUAGE, rec.DICTIONARY);
END LOOP;
END;
50. Автоматическое добавление словаря (DBMS_SCHEDULER)
BEGIN
DBMS_SCHEDULER.CREATE_JOB(
job_name => 'add_dict_job',
job_type => 'PLSQL_BLOCK',
job_action => 'DECLARE d CLOB := ''STEM scheduler noun''; BEGIN CTX_ANL.ADD_DICTIONARY(''dict35'',''ENGLISH'',d); END;',
start_date => SYSTIMESTAMP,
repeat_interval => 'FREQ=DAILY;INTERVAL=1',
enabled => TRUE
);
END;
Заключение
CTX_ANL расширяет возможности AUTO_LEXER в Oracle Text: добавление/удаление словарей,
поддержка сложных слов, морфологии и автоматизация. Примеры выше можно применять в реальных проектах.
Полезные ссылки