Вурдалак
Продвинутый новичок
Как реализовать индекс?
Есть достаточно большой текстовый файл, требуется организовать поиск по нему. Положа руку на сердце, как таковой проблемы с производительностью нет, учитывая кеш. Но интересует как можно повысить производительность самого поиска с помощью индекса, чисто на PHP.
Допустим, мой вариант.
Есть файл со всеми ключевыми словами (без stopwords и прошедшие через stemmer) типа
Каждое ключевое слово имеет макс. размер и хранится как 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):
Сам индекс для файла в ~ 1 Mb создаётся, к сожалению, около 2-х секунд... Зато после поиск без кеша относительно быстрый (0.002 - 0.05). Зависит от кол-ва результатов на страницу и кол-во найденных вхождений.
-~{}~ 15.10.10 00:42:
Там ещё требуется файлик «stopwords.txt» для теста.
Есть достаточно большой текстовый файл, требуется организовать поиск по нему. Положа руку на сердце, как таковой проблемы с производительностью нет, учитывая кеш. Но интересует как можно повысить производительность самого поиска с помощью индекса, чисто на PHP.
Допустим, мой вариант.
Есть файл со всеми ключевыми словами (без stopwords и прошедшие через stemmer) типа
Код:
абв [offset list from][offset list length]
абвг [offset list from][offset list length]
бац [offset list from][offset list length]
...
Есть второй файл со всеми смещениями в текстовом файле, т.е. «абв» встречается в требуемом текстовом файле на позициях 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);
-~{}~ 15.10.10 00:42:
Там ещё требуется файлик «stopwords.txt» для теста.