Re: Полнотекстовый поиск в БД
Буквариус, Православный, РПЦ МП - 11:13 04.07.2003
|
Если не найдете ничего уже готового, могу лишь описать решение, как сделать подобный поиск на любой СУБД самому, ручками. Решение состоит в создании нескольких дополнительных таблиц, хранящих подстроки книг и ссылки на нужные места. Некоторые поля этих таблиц индексируются, что обеспечивает быстрый поиск. Вашей задачей будет поддержание этих таблиц-"индексов" в актуальном виде: при добавлении новой книги дополнять таблицы новыми подстроками и ссылками, при удалении -- удалять уже ненужные записи, при модификации ... ну, чтоб не мучиться, на первых порах удалять и добавлять заново.
Структура и содержимое "индексных" таблиц зависит от тех задач, которые Вы хотите поставить перед поисковым алгоритмом. Если задачу ставить в лоб -- поиск по любой подстроке любой длины -- то размер индекса для одной книги будет пропорционален квадрату длины книги (речь не о размере переплета . Но обычно никому не нужен поиск по подстрокам размером с килобайт, так что...
Вот несколько примеров.
1. Поиск ведется по отдельным словам (словоформам). Создаем две таблицы, со словоформами и ссылками:
create table SubStrings (ID number primary key, SubString varchar2 (100));
create index on SubStrings (SubString);
create table Refs (ID number primary key, SubString_ID number, Book_ID number, OffsetInBook number);
create index on Refs (SubString_ID);
create index on Refs (Book_ID);
При добавлении новой книги обогащаем таблицу SubStrings новыми словами, а таблицу Refs -- всеми ссылками на каждое из слов. Если слово уже присутствует в SubStrings, мы его туда не добавляем, однако все ссылки на него все же прописываем.
При удалении книги удаляем все записи из Refs с Book_ID удаляемой книги, и все записи из SubStrings, на которые больше нет ссылок из Refs.
Поиск состоит в нахождении нужного слова в поле SubStrings.SubString и выводе всех ссылок на него. Чтобы поиск был быстрым, это поле проиндексировано средствами СУБД.
2. Поиск по подстроке размера от m до n. Структура таблиц та же. При добавлении книги обогащаем SubStrings всеми новыми встретившимися подстроками от m до n. Да, да, ручками, это не так уж сложно, как может показаться на первый взгляд, и не такого уж большого размера вследствие статистической природы языков. А ссылки дополняем ссылками на эти подстроки, и вот этого материала будет очень много, так что соразмеряйте ограничения m и n. Удаление книги и поиск аналогичны п.1.
3. Поиск только по словам и по группе слов.
Идея -- создать третью таблицу с цепочками слов (разумеется, в виде ID). Здесь возможны несколько решений. Неэкономичное, но простое и наглядное решение:
Пусть поиск ограничен N словами.
create table SubStrings (ID number primary key, SubString varchar2 (100));
create index on SubStrings (SubString);
create table WordSeries (ID number primary key, SubString1_ID number, SubString2_ID number, ... , SubStringN_ID number);
create index on WordSeries (SubString1_ID, SubString2_ID); -- больше и не надо
create table Refs (ID number primary key, WordSeries_ID number, Book_ID number, OffsetInBook number);
create index on Refs (WordSeries_ID);
create index on Refs (Book_ID);
Конструкция "..." наводит на мысли, но я не обещал, что решение красивое. Оно простое и наглядное.
Вставка книги. Таблицу SubStrings забиваем новыми словами, таблицу WordSeries -- новыми цепочками слов (в виде ссылок на слова, ненужные ID заполняем нулями), Refs -- ссылками на текст.
Удаление здесь более сложное. Долго писать, но при желании можно воплотить.
Поиск. Введенные пользователем слова отыскиваются в SubStrings (если хоть одного нет, выходим), далее ищется нужная цепочка (или начало цепочки, все зависит от того, как мы заполняли WordSeries, полными сериями, или сериями всех возможных размеров от 1 до N). Ссылки поступают в дальнейшую обработку.
Непростое, но более бережливое и общее решение состоит в построении цепочек слов в виде линейных списков. Вероятно, возможны и иные решения.
Уф. Ну, если найдете готовый механизм, то хоть будете представлять, как такие индексы устроены.
|
|