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

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

Для включения расширенных возможностей индексирования новостей необходимо проделать следующее:

Во время своей работы indexer в этом режиме в дополнение будет для каждого сообщения новостей определять Parent-ID (идентификатор статьи, на которую отвечает данное сообщение) и добавлять пары (Parent-ID, ID) в таблицу ссылок links.

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

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

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

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

3.11.2.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.2.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.

Для команд HTDBDoc и HTDBtext возможно указать свой regex-шаблон для сопоставления индексируемого URL с переменными HTDB:

HTDBText header "SELECT header FROM news WHERE section=$1 AND article=$2" "^/section/([0-9]+)/art/([0-9]+)\.html"

в этом случае regex-шаблон сопоставляется с полным путем и именем файла индексируемого URL.

Для команды HTDBText можно использовать и мета-переменные шаблона страницы выдачи (например, $(DP_ID), $(URL)) для формирования SQL-запроса, например:

HTDBText hint "SELECT hint FROM hints WHERE url = '$(url)'"

3.11.2.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.2.4. Индексирование веб-сервера, использующего SQL базу данных

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

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

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

http://search.site.ext/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.site.ext/board/message.php?id=*
Alias  http://search.site.ext/board/message.php?id=  htdb:/

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

http://search.site.ext/board/message.php?id=XXX

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

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

3.11.3. Индексирование вывода программ (виртуальные схемы 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.3.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.3.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.3.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.4. Зеркалирование

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

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.5. Сбор данных

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

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

Одина из опций add, update или delete задает когда эта команда выполняется, при индексировании нового документа, при переиндексировании, или при удалении документа. Если не указана ни одна опция, подразумеваетя опция add по умолчанию.

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

ActionSQL add body "\(([0-9]{3})\)[ ]*([0-9]{3})[- \.]*([0-9]{2})[- \.]*([0-9]{2})" "INSERT INTO phonedata(phone,title,id)VALUES('+7$1$2$3$4','$(title)',$(dp_id))"
ActionSQL update body "\(([0-9]{3})\)[ ]*([0-9]{3})[- \.]*([0-9]{2})[- \.]*([0-9]{2})" "UPDATE phonedata SET phone='+7$1$2$3$4',title='$(title)' WHERE id=$(dp_id)"
ActionSQL delete url "." "DELETE FROM phonedata WHERE id=$(dp_id)"