# Индексирование таблиц SQL баз данных (виртуальная URL схема `htdb:`)

DataparkSearch позволяет индексировать текстовые поля SQL баз данных используя так называемую виртуальную URL схему `htdb:`.

Используя виртуальную URL схему `htdb:/` вы можете создать полный индекс текстовых полей вашей SQL базы данных, а также вашего WWW сервера, использующего SQL для хранения информации.

Необходимо иметь PRIMARY индекс для таблиц, которые вы собираетесь индексировать.

## HTDB команды в `indexer.conf`

Для поддержки HTTDB в `indexer.conf` используются пять команд: `HTDBAddr`, `HTDBList`, `HTDBLimit`, `HTDBDoc` и `HTDBText`.

Команда `HTDBAddr
` служит для описания соединения с базой данных, таблицу или таблицы которой вы собираетесь индексировать. Её систаксис совпадает с синтаксисом команды `DBAddr`.

`HTDBList
` - это SQL запрос генерирования списка всех URL, соответсвующих записям в таблице по полю PRIMARY индекса. В команде `HTDBList` вы можете использовать и относительные и абсолютные URL.

Например:

    HTDBList "SELECT concat('htdb:/',id) FROM messages"
        или
    HTDBList "SELECT id FROM messages"

Команда
`HTDBLimit` задаёт максимальное число записей, считываемых из базы за один раз. Это позволяет избежать черезмерного использования памяти при индексировании больших таблиц. Пример:

    HTDBLimit 512

`HTDBDoc
` - это запрос для получения из базы записи, определенной по первичному ключу.

SQL запрос `HTDBList` используется для все URL, заканчивающихся символом '/'. Для остальных URL используется SQL запрос из `HTDBDoc`.

Запрос `HTDBDoc` должен возвращать ПОЛНЫЙ HTTP ответ с заголовками. Таким образом вы можете гибко управлять вашей системой индексирования выдавая различные HTTP коды статуса. См. для информации о реакции `indexer` на различные коды статуса HTTP.

Если по запросу `HTDBDoc` не будет найдено ни одной записи, система выборки HTDB сгенерирует ответ "HTTP 404 Not Found". Это может произойти при переиндексировании, если запись была удалена из вашей базы данных с момента предыдущего индексирования. Вы можете использовать команду `HoldBadHrefs 0` для удаления информации о таких записях и из таблиц DataparkSearch.

Вы можете использовать несколько команд `HTDBDoc/List` в одном файле `indexer.conf` с различными соответсвующими им командами `Server`.

`HTDBText <section>
` - это запрос для получения из базы простого текста, соответсвующего первичному ключу, полученному при помощи команды `HTDBList`. Параметр <section> задаёт имя секции, под которой этот текст будет индексироваться. Такой запрос может возращать несколько строк с данными, если это необходимо. Вы можете указать несколько команд `HTDBText` для каждой команды `Server` или `Realm`.

    DBAddr mysql://foo:bar@localhost/database/?dbmode=single

    HTDBAddr mysql://foofoo:barbar@localhost/database/

    HTDBList "SELECT DISTINCT topic_id FROM messages"

    HTDBText body "SELECT raw_text\
    FROM messages WHERE topic_id='$1'"

    Server htdb:/

Возможно задавать одновременно обе команды `HTDBDoc` и `HTDBText` для одной команды `Server` или `Realm`. В этом случае сначала обрабатываются команды `HTDBText`.

## Переменные HTDB

Вы можете использовать части пути в URL в качестве параметров для обоих SQL запросов `HTDBList` и `HTDBDoc`. Все части используются как $1, $2, ... $n, где число n - число поддиректорий в пути:

    htdb:/part1/part2/part3/part4/part5/
             $1    $2    $3    $4    $5

Например, пусть в `indexer.conf` указана команду:

    HTDBList "SELECT id FROM catalog WHERE category='$1'"

При использовании URL `htdb:/cars/`, $1 будет заменено на 'cars':

    SELECT id FROM catalog WHERE category='cars'

Вы можете использовать длинные URL при передаче нескольких параметров для обоих SQL запросов `HTDBList` и `HTDBDoc`. Например, `htdb:/path1/path2/path3/path4/id` с запросом:

    HTDBList "SELECT id FROM table WHERE field1='$1' AND field2='$2' and field3='$3'"

Это запрос создаст списое таких URL:

    htdb:/path1/path2/path3/path4/id1
    ...
    htdb:/path1/path2/path3/path4/idN

для всех значений поля `id` в результате выполенния запроса `HTDBList`.

## Создание текстового индекса

Используя схему `htdb:/` вы можете создать текстовый индекс и использовать его в ваших приложениях. Предположим, у вас есть большая SQL таблица, в которой хранятся, например, сообщения электронной доски объявлений в текстовом формате. И пусть вы хотите создать приложение, обладающее возможностью поиска среди этих объявлений. Допустим, сообщения храняться в таблице `messages` с двумя полями `id`, используемом в качестве первичного ключа, и `msg`, в котором собственно и храняться тексты объявлений. Поиск при помощи SQL LIKE операции может занять слишком много времени:

    SELECT id, message FROM message WHERE message LIKE '%someword%'

Используя DataparkSearch вы можете создать текстовый индекс по таблице `message`. Установите DataparkSearch обычным образом. Затем отредактируйте ваш `indexer.conf`:

    DBAddr mysql://foo:bar@localhost/database/?dbmode=single

    HTDBAddr mysql://foofoo:barbar@localhost/database/

    HTDBList "SELECT id FROM messages"

    HTDBDoc "SELECT concat(\
    'HTTP/1.0 200 OK\\r\\n',\
    'Content-type: text/plain\\r\\n',\
    '\\r\\n',\
    msg) \
    FROM messages WHERE id='$1'"

    Server htdb:/

После запуска `indexer` вставить URL 'htdb:/' в базу и выполнит SQL запрос, указанный в `HTDBList`. В результате вы получим значения 1,2,3, ..., N. Эти значения будут рассматриваться как ссылки относительно URL 'htdb:/'. Список новый URL в виде htdb:/1, htdb:/2, ... , htdb:/N будет добавлен в базу. Затем SQL запрос `HTDBDoc` будет выполнен для каждого из вновь добавленных URL. `HTDBDoc` создаст HTTP документ в виде:

    HTTP/1.0 200 OK
    Content-Type: text/plain

    <some text from 'message' field here>

Этот документ будет использован для создания текстового индекса по словам из полей 'message'. Слова будут сохранены в таблице 'dict' (предполагая, что используется способ хранения 'single').

После индексирования, вы можете использовать для поиска таблицы DataparkSearch:

    SELECT url.url
    FROM url,dict
    WHERE dict.url_id=url.rec_id
    AND dict.word='someword';

Так как таблица 'dict' имеет индекс по полю 'word', этот запрос будет выполнен быстрее, нежели запрос с использованием SQL LIKE оператора при запросе по таблице 'messages'.

Вы также можете задать несколько слов при поиске:

    SELECT url.url, count(*) as c
    FROM url,dict
    WHERE dict.url_id=url.rec_id
    AND dict.word IN ('some','word')
    GROUP BY url.url
    ORDER BY c DESC;

Оба запроса вернут значения 'htdb:/XXX' в поле urll.url. Ваше приложение может отбросить 'htdb:/' для получения значения первичного ключа таблицы 'messages'.

## Индексирование веб-сервера, использующего SQL базу данных

Вы можете также использовать виртуальную схему `htdb:/` для индексирования вашего веб-сервера, использующего базу данных для хранения отображаемой информации, без обращения к веб-серверу при индексировании. Т.е. намного быстрее и используя меньше ресурсов процессора нежели индексируя обращаясь к веб-серверу.

Основная идея похожа на создание текстового индекса, за исключением того, что поиск должен давать реальные URL вместо URL в виде 'htdb:/...'. Это достигается при помощи механизма алиасов DataparkSearch.

Команда `HTDBList` создаёт URL в форме:

    http://search.mnogo.ru/board/message.php?id=XXX

где XXX - значение первичного ключа таблицы "messages".

Для каждого значения первичного ключа команда `HTDBDoc` создаёт text/html документ с HTTP заголовком примерно такого вида:

    <HTML>
    <HEAD>
    <TITLE> ... subject field here .... </TITLE>
    <META NAME="Description" Content=" ... author here ...">
    </HEAD>
    <BODY> ... message text here ... </BODY>

В конце `doc/samples/htdb.conf` даны три команды:

    Server htdb:/
    Realm  http://search.mnogo.ru/board/message.php?id=*
    Alias  http://search.mnogo.ru/board/message.php?id=  htdb:/

Первая команда указывает `indexer` выполнить запрос `HTDBList`, который сгенерирует список сообщений в виде:

    http://search.mnogo.ru/board/message.php?id=XXX

Вторая команда позволяет `indexer` принимать такие URL сообщений.

Третья команда заменяет в URL подстроку "htdb:/" на подстроку "http://search.mnogo.ru/board/message.php?id=" при получении документа с сообщением. Что обозначает, что URL в виде `"http://mysearch.udm.net/board/message.php?id=xxx"` будет показан в результате поиска, хотя при индексировании будет использован URL `"htdb:/xxx"`, где xxx - значение первичного ключа, ID записи в таблице "messages".