В Oracle есть замечательная возможность осуществлять контекстный поиск по тексту, который в явном виде не хранится в таблице. Для того, чтобы воспользоваться этой возможностью необходимо написать функцию, которая по rowid целевой таблицы построит соответсвующую ей текстовую строку строку.
Прототип данной функции, или скорее процедуры, т.к. это процедура выглядит так:
procedure ctx_foo(p_rid in rowid, p_ctx_text in out nocopy varchar2);
p_rid - rowid таблицы, в которой находятся данные, которые мы будем искать
p_ctx_text - текст, который мы проиндексируем контекстным индексом для дальнейшего применения функции CONTAINS.
Далее надо настроить контекстный индекс при помощи функций: создать perference в словаре Oracle при помощи процедуры ctx_ddl.create_preference и установить его атрибуты при помощи процедуры ctx_ddl.set_attribute.
Теперь создаём контексный индекс, на любую колонку тип которой: VARCHAR2, CLOB, BLOB, CHAR, BFILE, XMLType, URIType.
create index <index_name> on <table_name(column_name) indextype is ctxsys.context parameters('<params>')
Подробности про параметры можно прочитать по ссылке: http://download.oracle.com/docs/cd/E11882_01/text.112/e16594/ind.htm#i1006887
Ниже я приведу пример создания контекстного индекса, у котрого строка для индексации генерируется процедурой.
Создаём таблицы и заполняем их исходными данными.
create table ctx_source(
grp number,
word varchar2(32),
pos number);
insert into ctx_source values (1, 'Oracle', 1);
insert into ctx_source values (1, 'database', 2);
insert into ctx_source values (1, '11g', 3);
insert into ctx_source values (2, 'Mary', 1);
insert into ctx_source values (2, 'had', 2);
insert into ctx_source values (2, 'a', 3);
insert into ctx_source values (2, 'little', 4);
insert into ctx_source values (2, 'lamb', 5);
insert into ctx_source values (3, 'Lamb', 1);
insert into ctx_source values (3, 'with', 2);
insert into ctx_source values (3, 'sauce', 3);
create table ctx_foo (
id number,
ctx_text varchar2(1));
insert into ctx_foo(id) values (1);
insert into ctx_foo(id) values (2);
insert into ctx_foo(id) values (3);
Создаём пакеты с функциями
create or replace
package ctx as
procedure ctx_foo(p_rid in rowid, p_ctx_text in out nocopy varchar2);
function print_foo(p_id in number) return varchar2;
end ctx;
create or replace
package body ctx as
procedure ctx_foo(p_rid in rowid, p_ctx_text in out nocopy varchar2)
is
begin
for r in (select word
from ctx_source
where grp = (select id from ctx_foo where rowid = p_rid)
order by pos)
loop
p_ctx_text := p_ctx_text || r.word || ' ';
end loop;
p_ctx_text := rtrim(p_ctx_text);
end ctx_foo;
function print_foo(p_id in number) return varchar2
is
l_return varchar2(256);
begin
for r in (select word
from ctx_source
where grp = p_id
order by pos)
loop
l_return := l_return || r.word || ' ';
end loop;
return rtrim(l_return);
end print_foo;
end ctx;
Создаём perference
exec ctx_ddl.create_preference( 'foo_datastore', 'user_datastore' );
exec ctx_ddl.set_attribute('foo_datastore', 'procedure', 'ctx.ctx_foo');
exec ctx_ddl.set_attribute('foo_datastore', 'output_type', 'varchar2');
Создаём индекс на основе нашего perference
create index index_ctx_foo on ctx_foo(ctx_text) indextype is ctxsys.context parameters( 'datastore foo_datastore sync (on commit)');
/*sync (on commit) необходимо, чтобы индекс обновлялся автоматически при втавке новых данных, этот параметр не обязательный*/
Тестируем
select id, ctx.print_foo(id) from ctx_foo where contains(ctx_text,'lamb') > 0;
id ctx.print_foo(id)
------------------------
2 Mary had a little lamb
3 Lamb with sauce
select id, ctx.print_foo(id) from ctx_foo where contains(ctx_text,'oracle') > 0;
id ctx.print_foo(id)
------------------------
1 Oracle database 11g
Желаю успешно использовать в своей работе контекстный индексы. У Oracle есть целый гайд работе с Oracle Text, прочитать его можно по адресу: http://download.oracle.com/docs/cd/E11882_01/text.112/e16594/toc.htm
Комментариев нет:
Отправить комментарий