Pues como quedamos, esta es la solución que implemente para las búsquedas.
1. Modifiqué mi tabla en la DB (Postgresql) para almacenar al contenido de cada documento. Mi tabla se llama "planti_corr", agregué un campo de texto e indexé la tabla por ese campo siguiendo lo indicado por
mamcx y en la documentación
http://www.postgresql.org/docs/9.1/s...extsearch.html
Código SQL
[-]CREATE INDEX pgcontenido_idx
ON planti_corr
USING gin
(to_tsvector('spanish'::regconfig, contenido));
2. Ahora que extraer el contenido de cada documento que se vaya a dar de alta, esto lo hice en el botón de "Altas" en el formulario de registro de documentos:
- Crear una instancia del Portapapeles de Windows
- Crear una instancia de Word y abrir el documento
- Seleccionar todo el contenido del documento de Word y copiarlo en el Portapapeles de Windows
- Cerrar Word
- Poner el contenido del Portapapeles en una variable
- El límite de tsvector en Postgresql es de 1048575 bytes por lo que limito el tamaño del contenido de la variable a 1040000 con la función LeftBStr()
- Envío todo a Postgres en un Query
Código Delphi
[-]
var
word : Variant;
plantiOrig : TClipBoard;
wnContenido : WideString;
wnGuarda : oleVariant;
begin
...
...
Word := CreateOleObject('Word.Application');
Word.Visible := False;
try
Word.Documents.Open(, EmptyParam, EmptyParam, EmptyParam,
EmptyParam, EmptyParam, EmptyParam, EmptyParam,
EmptyParam, EmptyParam);
Word.Selection.WholeStory; Word.Selection.Copy; Word.ActiveDocument.Close(wnGuarda, EmptyParam, EmptyParam);
Word.Quit;
wnContenido := LeftBStr(plantiOrig.AsText, 1040000); plantiOrig.Clear;
Query1.Active := False;
Query1.SQL.Clear;
Query1.SQL.Add('insert into planti_corr (nombre, archivo, contenido) values (:vNombre, :vArchivo, :vContenido)');
Query1.ParamByName('vNombre').AsString := ;
Query1.ParamByName('vArchivo').AsString :=
Query1.ParamByName('vContenido').AsWideString := wnContenido;
Query1.ExecSQL;
Except
Application.MessageBox('Error al cargar el archivo en la base de datos', 'Buscador', MB_OK or MB_ICONERROR);
End;
...
...
end;
3. Ahora la búsqueda. En otro botón:
- Tomo el texto con las palabras que desean buscar, éstas deben quedar separadas únicamente por el símbolo '&' (primerapalabra&segundapalabra&tercerapalabra); (no espacios, no comas, no puntos, no... nada) y asigno la nueva cadena a una variable, para esto utilizo la función ReplaceStr()
- Ejecuto la consulta esta debe ser con la función "tsquery" de Postgres en el campo indexado, (que el servidor haga todo!!!)
- ... y hago muy feliz a mi usuario !!!
Código Delphi
[-]
var
w_palabras : String;
wpTotalReg : Integer;
begin
...
...
w_palabras := ReplaceStr(edtFrases.Text,' ', '&');
Query1.Close;
Query1.SQL.Clear;
Query1.SQL.Add('SELECT id_planti, nombre, archivo FROM planti_corr WHERE contenido @@ to_tsquery(:wqPalabras)');
Query1.ParamByName('wqPalabras').AsString := w_Palabras;
Query1.Open;
wpTotalReg := Query1.RecordCount;
...
...
end;
Estas son las instrucciones básicas, obviamente hay cosas antes y después, pero concretando esta es la forma en que lo solucioné y efectivamente el tiempo de la búsqueda se redujo de algunos minutos a pocos segundos, bastante bien diría yo!!!.
Muchas gracias a todos, especialmente a mamcx y a D-MO por sus ideas (prácticamente la solución)
Saludos.
Eduardo Laguna