Pular para o conteúdo

Oracle Text: Indexação, pesquisa e análise de textos e documentos binários

Um pouco do Oracle Text …

O Oracle Text é uma feature embutida no banco de dados que utiliza a linguagem SQL para indexar, pesquisar e analisar textos e documentos binários armazenados nas tabelas. Nas versões Oracle 11g, 10g e 9i, essa feature é conhecida como Oracle Text. No Oracle 8i é conhecida como Oracle Intermedia e, no Oracle 8, a mesma é conhecida como Oracle Context. Esta tecnologia oferece uma solução completa para pesquisa de textos na qual a mesma permite filtrar e extrair textos de conteúdos de diferentes formatos de documentos. O Oracle Text suporta mais de 150 formatos de documentos, incluindo os mais populares como os documentos Microsoft Office, além de formatos de arquivo do Adobe PDF, arquivos HTML e XML. Neste artigo irei demonstrar como gravar um documento binário (.doc) no banco de dados Oracle 10g Express Edition e o que fazer para poder realizar pesquisas no seu conteúdo. Para maiores informações sobre esta tecnologia, acesse a página oficial do Oracle Text no site da Oracle.

O arquivo que irei carregar para o banco de dados (arquivo.doc) possui o conteúdo mostrado na figura abaixo.

1

Então vamos realizar um teste prático …

C:\>sqlplus /@XE as sysdba

SQL*Plus: Release 10.1.0.2.0 - Production on Qua Jun 11 08:52:26 2008

Copyright (c) 1982, 2004, Oracle.  All rights reserved.

Conectado a:
Oracle Database 10g Express Edition Release 10.2.0.1.0 - Production

-- Criação de um usuário para teste
SYS> create user scott identified by tiger default tablespace users quota unlimited on users;

Usuário criado.

SYS> grant connect,resource to scott;

Concessão bem-sucedida.

-- Criação de um diretório que indica a localização do arquivo (.doc)
SYS> create or replace directory documentos as 'c:\docs';

Diretório criado.

SYS> grant read on directory documentos to scott;

Concessão bem-sucedida.

SYS> connect scott/tiger@XE
Conectado.

-- Criação de uma tabela de teste
SCOTT> create table teste (
2    id number,
3    nome varchar2(20),
4    documento blob
5  );

Tabela criada.

-- Criação de uma stored procedure para carregar o arquivo para o banco de dados
SCOTT> create or replace procedure carrega_arquivo (p_file_name in teste.nome%type)
2  as
3   v_bfile bfile;
4   v_blob blob;
5  begin
6    insert into teste (id,nome,documento)
7    values (1,p_file_name,empty_blob())
8    return documento into v_blob;
9    v_bfile := bfilename('DOCUMENTOS',p_file_name);
10    dbms_lob.fileopen(v_bfile, dbms_lob.file_readonly);
11    dbms_lob.loadfromfile(v_blob,v_bfile,dbms_lob.getlength(v_bfile));
12    dbms_lob.fileclose(v_bfile);
13    commit;
14  end;
15  /

Procedimento criado.

-- Carregando o arquivo para a tabela
SCOTT> execute carrega_arquivo('arquivo.doc');

Procedimento PL/SQL concluído com sucesso.

SCOTT> select id,nome from teste;

      ID NOME
---------- --------------------
       1 arquivo.doc

-- Verificando o tamanho do arquivo binário carregado
SCOTT> select dbms_lob.getlength(documento) bytes from teste;

BYTES
----------
   19968

-- Criando um índice do tipo context que permitirá a pesquisa textual
SCOTT> create index i_teste_documento on teste (documento)
   2  indextype is ctxsys.context parameters ('sync (on commit)');

Índice criado.

-- Verificando se houve algum erro na criação do índice
SCOTT> select * from ctx_user_index_errors;

não há linhas selecionadas

Abaixo, podemos verificar que após a criação do índice I_TESTE_DOCUMENTO na coluna DOCUMENTO, algumas tabelas e índices adicionais foram criados

SCOTT> select table_name from user_tables;

TABLE_NAME
------------------------------
TESTE
DR$I_TESTE_DOCUMENTO$I
DR$I_TESTE_DOCUMENTO$K
DR$I_TESTE_DOCUMENTO$N
DR$I_TESTE_DOCUMENTO$R

SCOTT> select index_name,table_name from user_indexes;

INDEX_NAME                     TABLE_NAME
------------------------------ ------------------------------
I_TESTE_DOCUMENTO              TESTE
SYS_IL0000014279C00003$        TESTE
DR$I_TESTE_DOCUMENTO$X         DR$I_TESTE_DOCUMENTO$I
SYS_IL0000014285C00006$       DR$I_TESTE_DOCUMENTO$I
SYS_IL0000014290C00002$       DR$I_TESTE_DOCUMENTO$R
SYS_IOT_TOP_14288              DR$I_TESTE_DOCUMENTO$K
SYS_IOT_TOP_14293              DR$I_TESTE_DOCUMENTO$N

7 linhas selecionadas.

Apenas por curiosidade, podemos perceber que a tabela abaixo armazena o texto puro extraido do documento binário que foi carregado na coluna DOCUMENTOS da tabela TESTE

SCOTT> select token_text from DR$I_TESTE_DOCUMENTO$I;

TOKEN_TEXT
----------------------------------------------------
EDUARDO
ISTO
LEGATTI
ORACLE
POR
TESTE
TEXT
UM
É

9 linhas selecionadas.

Realizando a Pesquisa Textual

SCOTT> select id,nome from teste where contains(documento, 'legatti', 1) > 0;

      ID NOME
---------- --------------------
       1 arquivo.doc

SCOTT> select id,nome from teste where contains(documento, 'Oracle', 1) > 0;

      ID NOME
---------- --------------------
       1 arquivo.doc

SCOTT> select id,nome from teste where contains(documento, 'Eduardo', 1) > 0;

      ID NOME
---------- --------------------
       1 arquivo.doc

SCOTT> select id,nome from teste where contains(documento, 'nao existe', 1) > 0;

não há linhas selecionadas

No mais, para manutenção do índice caso necessário, poderemos utilizar alguns procedimentos como CTX_DDL.SYNC_INDEX para sincronização do índice porque nem todos os índices são atualizado automaticamente quando registros são adicionados ou deletados, ou CTX_DDL.OPTIMIZE_INDEX para reconstruir o índice quando necessário.

Voltando ao Passado …

Apenas fazendo uma comparação, se estivéssemos utilizando o já obsoleto Oracle 8 (8.0.5), esta tarefa seria um pouco mais complicada, pois teríamos que instalar e configurar o Oracle Context Cartridge e ainda realizar as tarefas abaixo:

Iniciar o serviço do Oracle Context

windows  -> ctxsvr80 -user ctxsys/ctxsys -personality qdml (m -> reindexa em background)
linux    -> ctxsrv -user ctxsys/ctxsys -personality m &

-- Criar o índice
execute ctx_ddl.create_policy('documento','teste.documento');
execute ctx_ddl.create_index('documento');

Quão útil foi este post ?

Clique em uma estrela para classificar o post

nota média 5 / 5. Contagem de votos: 31

Sem votos ! Seja o primeiro a classificar !

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

plugins premium WordPress