DataparkSearch Engine 4.53: Справочное руководство
Пред. | Глава 3. Индексирование | След.

# 3.11. Расширенные возможности индексирования

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

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

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

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

### 3.11.1.1. 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 коды статуса. См. Разд. 3.2> для информации о реакции 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.

### 3.11.1.2. Переменные 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`.

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

Используя схему `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'.

### 3.11.1.4. Индексирование веб-сервера, использующего 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".

## 3.11.2. Индексирование вывода программ (виртуальные схемы URL `exec:` и `cgi:`)

DataparkSearch поддерживает виртуальные URL схемы `exec:` и `cgi:`, позволяющие запускать внешнюю программу. Эта программа должна выдавать результат своей работы в `stdout`. Результат должен быть оформлен по стандарту HTTP, т.е. заголовок ответа HTTP, а за ним содержимое документа.

Например, при индексировании обоих `cgi:/usr/local/bin/myprog` и `exec:/usr/local/bin/myprog`, indexer будет выполнять программу `/usr/local/bin/myprog`.

### 3.11.2.1. Передача параметров для виртуальный схемы `cgi:`

При выполнении программы по виртуальной схеме `cgi:`, indexer эмулирует выполнение из-под HTTP сервера. Он создаёт переменную окружения REQUEST_METHOD со значением "GET" и переменную QUERY_STRING в соответствии со стандартами HTTP. Например, при индексировании `cgi:/usr/local/apache/cgi-bin/test-cgi?a=b&d=e` indexer создаёт QUERY_STRING со значением `a=b&d=e`. Виртуальная URL схема `cgi:` позволяет индексировать ваш сайт без веб-сервера, даже если необходимо индексировать CGI скрипты. Например, если для вашего веб-сервера статические документы находятся в `/usr/local/apache/htdocs/`, а CGI скрипты в `/usr/local/apache/cgi-bin/`, используёте следующую конфигурацию:

    Server http://localhost/
    Alias  http://localhost/cgi-bin/	cgi:/usr/local/apache/cgi-bin/
    Alias  http://localhost/		file:/usr/local/apache/htdocs/

### 3.11.2.2. Передача параметров для виртуальной схемы `exec:`

indexer не создаёт переменной окружения QUERY_STRING как для схемы `cgi:`. Он создаёт командную строку с аргументами, указанными в URL после занка ?. Например, при индексировании `exec:/usr/local/bin/myprog?a=b&d=e`, будет выполнена слудующая команда с параметрами:

    /usr/local/bin/myprog "a=b&d=e"

### 3.11.2.3. Использование виртуальной URL схемы `exec:` в качестве внешней системы получения

Виртуальную URL схему `exec:` можно использовать в качестве внешней системы получения документов. Это позволяет использовать для получения документов протоколы, не поддерживаемые DataparkSearch. Например, можно испрользовать программу curl, доступную с http://curl.haxx.se/ для индексирования HTTPS сайтов.

Поместите этот короткий скрипт в `/usr/local/dpsearch/bin/` под именем `curl.sh`.

    #!/bin/sh
    /usr/local/bin/curl -i $1 2>/dev/null

Этот скрипт берёт URL, указанный в качестве параметра командной строки и выполняет программу curl для получения этого документа. Ключ `-i` говорит curl выводить результат вместе с HTTP заголовками.

Теперь вы можете использовать такие команды в вашем `indexer.conf`:

    Server https://some.https.site/
    Alias  https://  exec:/usr/local/dpsearch/etc/curl.sh?https://

При индексировании `https://some.https.site/path/to/page.html`, indexer преобразует этот URL в

    exec:/usr/local/dpsearch/etc/curl.sh?https://some.https.site/path/to/page.html

выполнит скрипт `curl.sh`:

    /usr/local/dpsearch/etc/curl.sh "https://some.https.site/path/to/page.html"

и получит его вывод для дальнейшей своей работы.

## 3.11.3. Зеркалирование

Вы должны указать путь к корневой директории для активации зеркалирования сайтов

    MirrorRoot /path/to/mirror

Вы также можете указать корневую директорию для хранения заголовков зеркалируемых документов, в этом случае indexer будет также записывать на диск HTTP заголовки.

    MirrorHeadersRoot /path/to/headers

Вы можете также указать период, в течении которого будут использоваться файлы из зеркала, вместо выкачивания оригинальных документов.

    MirrorPeriod <time>

Зеркалирование очень полезно когда вы экспериментируете с индексированием DataparkSearch одних и тех же хостов и не хотите создавать много трафика в/из интернета. Если не задан `MirrorHeadersRoot` и тем самым заголовки не сохраняются на локальном диске, тогда тип файлов определяется по значениям, заданным командами `AddType`. Значение `MirrorPeriod` по умолчанию равно -1, что означает `не использовать зеркалированые файлы`.

<time> указывается в форме `xxxA[yyyB[zzzC]]` (пробелы допускаются между xxx и A и yyy и т.д.), где xxx, yyy, zzz - числа (могут быть отрицательными!). A, B, C могут быть одним из:

    		s - секунда
    		M - минута
    		h - час
    		d - день
    		m - месяц
    		y - год

(эти буквы такие же, как и в функциях `strptime`/`strftime`)

Примеры:

    15s - 15 секунд
    4h30M - 4 часа и 30 минут
    1y6m-15d - 1 год и шесть месяцев минус 15 дней
    1h-10M+1s - 1 час минус 10 минут плюс 1 секунда

Если указано только число без какой-либо буквы, считается, что время указано в секундах (это сделано для совместимости с версиями, младше 3.1.7).

Следующая команда задаёт использование локальных копий в течении одного дня:

    MirrorPeriod 1d

Если ваши страницы уже проиндексированы, и вы реиндексируете с ключом `-a`, indexer будет проверять только заголовки и выкачивать только файлы, изменённые с момента предыдущего индексирования. Таким образом, все неизменившиесы файлы не будут выкачиваться, и тем самым не будут и зеркалироваться. Для создания зеркала, вам необходимо либо очистить базу и начать заново, либо использовать ключ `-m`.

Вы можете использовать созданное зеркало как полноценное зеркало вашего сайта. Тем не менее, обратите внимание: indexer не выкачивает документ, имеющий размер более `MaxDocSize`, вернее, усекает размер файлов до этого значения, если оно превышено. Если ваш сайт не cодержит таких больших документов, все будет нормально.

## 3.11.4. Сбор данных

Используя команду ActionSQL вы можете выполнять SQL-запросы с данными документа во время индексирования. Команда ActionSQL имеет следующий синтаксис:

    ActionSQL <section> <pattern> <sql-template> [<dbaddr>]

где <section> - имя секции, содержимое которой будет проверяться на соответствие шаблону регулярного выражения <pattern>, если соответствие будет найдено, то будет заполнен шаблон sql-запроса <sql-template>, в котором наряду с мета-переменными регулярного выражения $1-$9 можно использовать и мета-переменные шаблона страницы выдачи (например, $(title), $(Last-Modified)). Заполненый sql-запрос будет выполнен в первом DBAddr, указанном в файле конфигурации, или в новом соединении с sql-базой, задаваемой необязательным параметром <dbaddr>.

Таким образом, команда ActionSQL предназначена для поиска и сбора различной информации с индексируемых страниц. Например, следующая команда будет собирать в таблицу phonedata все найденные номера телефонов и заголовки страниц, на которых эти номера указаны:

    ActionSQL body "\(([0-9]{3})\)[ ]*([0-9]{3})[- \.]*([0-9]{2})[- \.]*([0-9]{2})" "INSERT INTO phonedata(phone,title)VALUES('+7$1$2$3$4','$(title)')"

Пред. | Начало | След.
Остальные команды, используемые в `indexer.conf` | Уровень выше | Использование syslog