Как реализовать индекс?

Вурдалак

Продвинутый новичок
Как реализовать индекс?

Есть достаточно большой текстовый файл, требуется организовать поиск по нему. Положа руку на сердце, как таковой проблемы с производительностью нет, учитывая кеш. Но интересует как можно повысить производительность самого поиска с помощью индекса, чисто на PHP.

Допустим, мой вариант.

Есть файл со всеми ключевыми словами (без stopwords и прошедшие через stemmer) типа
Код:
абв     [offset list from][offset list length]
абвг    [offset list from][offset list length]
бац     [offset list from][offset list length]
...
Каждое ключевое слово имеет макс. размер и хранится как CHAR в MySQL (справа пробелами дополняется), 4 байта под расположение списка смещений во втором файле (см. дальше) и ещё 4 под длину списка смещений. Лексикографический порядок требуется для бинарного поиска по списку ключевых слов.

Есть второй файл со всеми смещениями в текстовом файле, т.е. «абв» встречается в требуемом текстовом файле на позициях 10, 2342, 4098, 820582 etc, слово «абвг» встречается на каких-то других позициях etc.

При поиске просто достаём смещения и по ним выводим нужный кусок текста из файла

Как это можно сделать по-другому?

-~{}~ 13.10.10 03:58:

В принципе, stemmer можно заменить на тот же phpMorphy (получать начальную форму слова перед занесением в список ключевых слов).

-~{}~ 13.10.10 04:03:

Перестройка индекса требоваться практически не будет (файл только для чтения).

-~{}~ 15.10.10 00:41:

Сделал нечто подобное (всё для windows-1251):
PHP:
$query = 'Съешь ещё этих мягких французских булок, да выпей чаю';
$file = 'someBigFile.txt';
$index = 'tmp/someBigFile.index';
$andLogic = TRUE; // AND, OR
$neighbourhood = 1000; // "Близость" искомых слов для логики "AND"

// Постраничная навигация
$offset = 0;
$limit = 10;

$dataSearch = new DataSearch();
$dataSearch->setFile($file, $index)->setNeighbourhood($neighbourhood);

$result = $dataSearch->getResult($query, $andLogic);

echo '<p>Всего: ' . $result->countEntries() . '</p>';

$fh = fopen($file, 'rb');

$patterns = array();

foreach($result->getKeywords() as $keyword) {
    $patterns[] = '/' . preg_quote($keyword, '/') . '[а-яА-ЯёЁa-zA-Z0-9-]*/i';
}

foreach($result->getEntries($offset, $limit) as $entry)
{
    fseek($fh, max($entry - $neighbourhood, 0));
    $text = preg_replace($patterns, '<b>\\0</b>', htmlspecialchars(fread($fh, 2 * $neighbourhood)));
    echo '<p>... ' . $text . ' ...</p>';
}

fclose($fh);
Сам индекс для файла в ~ 1 Mb создаётся, к сожалению, около 2-х секунд... Зато после поиск без кеша относительно быстрый (0.002 - 0.05). Зависит от кол-ва результатов на страницу и кол-во найденных вхождений.

-~{}~ 15.10.10 00:42:

Там ещё требуется файлик «stopwords.txt» для теста.
 

Вурдалак

Продвинутый новичок
Здесь мало кого интересует теоретическая (алгоритмическая) сторона вопроса. Моя ошибка.
 

Духовность™

Продвинутый новичок
Автор оригинала: Вурдалак
Здесь мало кого интересует теоретическая (алгоритмическая) сторона вопроса. Моя ошибка.
здесь вообще мало кого интересует теория, на большинство вопросов можно получить ответы стиле юзай %username%

я не такой умный
 

Вурдалак

Продвинутый новичок
A1x, спасибо за наводку. Zend_Search_Lucene лучше подходит для поиска по большому числу документов не очень большого размера. У меня немного другая задача: сам документ очень большой, но один. Разбивать его на какие-то страницы вряд ли выйдет, т.к. искомые слова могут быть на стыке 2-х страниц. Но там есть свои вкусности, да.
 

AmdY

Пью пиво
Команда форума
Вурдалак
разбей большой документ по обзацам на кучу маленьких документов
 

Вурдалак

Продвинутый новичок
AmdY, как вариант можно и так, но:
1) трудно выделить абзацы в некоторых текстовых файлах
2) одно слово может быть в конце абзаца, а второе — в начале следующего.
 

iceman

говнокодер
Вурдалак
> 2) одно слово может быть в конце абзаца, а второе — в начале следующего.

ищи 2 раза по каждому слову...
 

Вурдалак

Продвинутый новичок
iceman, ключевых слов может быть 3, 4, 5 etc

Плюс надо знать точное расположение вхождений, чтобы чётко вывести отрывок, где встречаются сразу все искомые слова. Search Lucene где-то смещение показывает?..

-~{}~ 16.10.10 23:35:

Кстати, Sphinx с файлами работает аналогично Lucene?
 
Сверху