Привет!

> А идея вашей проги такая же как у Димы? Т.е. если идет поиск по фразе,
> то делается джойн таблицы на себя саму? Или же немного хитрее?

Ща спою :)

Так вот, вкратце о задаче: имеется база нормативных актов (ну
вообще-то это типа эталон, но у меня волосы дыбом встали, когда я
увидел данные, которые надо было импортировать). Всего в базе около
70000 тысяч документов (примерно по 35к на каждом языке). Общий объем
текстовых данных - с выкинутым форматированием HTML - около 700
метров, с форматированием - почти полтора гига. Документы имеют кучу
всяких признаков - эмитент, источник публикации (не знаю как у вас, а
у нас закон вступает в силу только после публикации в особом журнале -
Официальном Мониторе), дату вступления в силу (он может вступать в
силу через год, например) и кучу всяких параметров (гораздо больше,
чем это выставленно наружу). Но самая большая проблема до сих пор была
в том, что поиск по ключевым фразам делался только в заголовке и
строго по введенному слову - т.е. там был обычный фуллскан на
containing в заголовке (на мускуле). Перед нами была поставлена задача
прикрутить туда полнотекстовый поиск (с некоторыми ограничениями,
об этом ниже). Сейчас это все работает в тестовом режиме ( по
адресу http://lex.justice.md/ можно увидеть, только переключить язык
не забудьте).

Сразу скажу, почему не прикрутили MnogoSearch - дело в том, что помимо
вебовского интерфейса нам надо сделать прогу, с такой же мордой, но
которую можно было бы юзать независимо от Инета - хотя обновляться,
разумеется, по нему родимому придется. Прога под винду. Mnogosearch
под винду во-первых платный (я хочу посмотреть, как наши госконторы
заплатят за непонятно какую лицензию), во-вторых мы бы явно не влезли
в бюджет, в-третьих я боялся, что мы банально не успеем прикрутить тот
же MnogoSearch.

Как решили. Взяли словарики румынского и русского языков (сейчас от
ispell) и загнали их в базу - т.е. конструкция типа

президент президента президенту президентом и т.д.

была побита на пары (NF, WF1), (NF, WF2), ... где NF - контрольная
сумма (CRC32) начальной формы ("президент"), а WFn - это контрольные
суммы всех производных от начальной формы, допустимых по правилам
конкретного языка.
Итого, в словарике имеем почти миллион записей.
Затем парсер разбивает очищенный документ на слова, слова меньше 3-х
символов игнорируются (таким образом бОльшая часть слов-связок в
румынском просто пропускается). Как непаханное поле для оптимизации мы
оставили выкидывание всяких слов, которые не несут смысловой нагрузки,
но больше 3-х символов (для русского языка, это будет "например",
"потому" и т.д.). После этого, все варианты слов заменяются на
нормальную форму для данного слова - разумеется, то, что не попадает в
словарик (какой-нибудь специфический термин или слово, написанное с
АшиПкой) - считается нормальной формой самого себя. Так как нам не
требовалось хранить ВСЕ вхождения ВСЕХ слов во ВСЕ документы, то для
каждого документа мы во-первых храним лишь количество таковых
вхождений и первые три вхождения - позиции слов - чтобы можно было
выкусывать цитаты. Это слегка позволило сэкономить количество
поисковых индексов - всего, например, для документов на русском языке
в телах документов содержится 15 768 228 слов (для румынского языка
18 528 190, но там слов-связок много больше) (имеется ввиду все
вхождения - и нормальных форм и их производных), тогда как всего
индексных записей - чуть более 12 000 000 для обоих языков - т.е.
почти троекратная экономия за счет некоторого упрощения
функциональности, которая в нашем случае нафиг не нужна.

ФФсе, полнотекстовый поиск готов. Да, а где временные виртуальные таблицы? ;-)
А вот где.

Когда пользователь вводит ключевые слова, для каждого ключевого слова
ищется его нормальная форма. В результате имеется набор чисел. И
строится вот такой простой запрос (в качестве ключевых слов
использовалось "президенту республики молдова" - регистр значения не
играет), запрос уже с подставленными значениями, привожу первый из
запросов, второй ничем, кроме списка полей вместо count() не
отличается, кому интересно - гляньте в исходники страницы после
выдачи результатов, они идут в виде комментариев:

Подсчет количества найденных документов (ну вот захотелось им
такую фичу и все):

select count(d.id)  from t_documents d,
       (select w.document_id, count(1) as cnt from t_search_words w,
               ( select 2624961196 as wrd from rdb$database union
                 select 1902388292 as wrd from rdb$database  union
                 select 1228066714 as wrd from rdb$database  ) t1
        where w.lang_id=2 and w.flag=1 and w.word=t1.wrd
        group by 1 order by 2 desc ) idx
 where d.lang_id=2  and d.published_when>='01.07.2002'  and
 d.published_when<='02.07.2007'  and d.publisher_id =36149  and 
d.id=idx.document_id and idx.cnt=3

Тут все просто - виртуальную табличку, в которой содержатся слова для
поиска объединяем с поисковыми индексами, а результат объединения -
объединяем с таблицей с документами. Указание найти все три слова -
последний and . Про то, что логически правильнее
было бы использовать union all я знаю, но ключевые слова 2 раза не
указывают.
Если кто сможет указать более оптимальный вариант запроса - и такой же
понятный - буду очень признателен. Пока же в самом худшем случае
запрос исполняется секунд двадцать (первый запрос, пока система базу
незакэшировала). Потом все летает пулей. У конкурентов слово Молдова
ищется 5 минут (!!!).
Размер базы - 2.5 Гига, на сервере памяти - 4Г. Некоторые параметры
Птица изменены - если кого интересует, приведу полностью. Классик 2.0.1.
Линух. Все, можно пинать ногами.


З.Ы. 2 ДЕ или Влад - а лимит на количество записей в одной таблице
сейчас какой? В релизнотах не нашел.



-- 
Best regards,
 Sergey                            mailto:[EMAIL PROTECTED]


Ответить