27.5. API для построения запросов

В дополнение к автоматическому парсингу запросов есть возможность строить запросы через API.

Пользовательские запросы могут быть объединены с запросами, созданными через API. Используйте парсер запросов для построения запроса из строки.

<?php
$query = Zend_Search_Lucene_Search_QueryParser::parse($queryString);

27.5.1. Исключения, бросаемые парсером запросов

Парсер запросов может генерировать два типа исключений:

  • Zend_Search_Lucene_Exception бросается, если ошибка произошла в самом парсере запросов.

  • Zend_Search_Lucene_Search_QueryParserException бросается в случае ошибки синтаксиса запроса.

Будет хорошей идеей отлавливать запросы Zend_Search_Lucene_Search_QueryParserException и выводить соответствующее сообщение.

<?php
try {
    $query = Zend_Search_Lucene_Search_QueryParser::parse($queryString);
} catch (Zend_Search_Lucene_Search_QueryParserException $e) {
    echo "Query syntax error: " . $e->getMessage() . "\n";
}

Тот же самый подход может (и должен) применяться для метода find() объекта Zend_Search_Lucene.

27.5.2. Простой запрос (запрос по одному ключевому слову)

Простые запросы предназначены для поиска по одному элементу.

Строка запроса:

word1
        

или

Построение запроса через API:

<?php
$term  = new Zend_Search_Lucene_Index_Term('word1', 'field1');
$query = new Zend_Search_Lucene_Search_Query_Term($term);
$hits  = $index->find($query);

Параметр, задающий поле для поиска ('field1'), является опциональным. Zend_Search_Lucene производит поиск по всем полям, если поля для поиска не заданы.

<?php
$term  = new Zend_Search_Lucene_Index_Term('word1');  // Search 'word1' through all indexed fields
$query = new Zend_Search_Lucene_Search_Query_Term($term);
$hits  = $index->find($query);

27.5.3. Составной запрос (запрос по нескольким ключевым словам)

Составные запросы предназначены для поиска по набору элементов.

Каждый элемент в наборе может быть определен как "обязательный", "необязательный" или "запрещенный".

  • "обязательный" элемент означает, что документы, которые не соответствуют данному элементу, не соответствуют всему запросу;

  • "запрещенный" элемент означает, что документы, соответствующие данному элементу, не соответствуют всему запросу;

  • в случае "необязательного" элемента документы не обязательно должны соответствовать (или не иметь соответствия) элементу. Тем не менее, документ должен соответствовать хотя бы одному элементу, чтобы соответствовать запросу.

Это значит, что если необязательные элементы добавлены в запрос с обязательными, то они будут иметь одинаковый набор результатов, но в случае второго запроса хиты, соответствующие необязательным элементам, будут перемещены в верх списка результатов запроса.

Для составных запросов могут использоваться оба метода поиска.

Запрос в виде строки:

+word1 author:word2 -word3
  • '+' используется для определения обязательного элемента

  • '-' используется для определения запрещенного элемента

  • Приставка 'field:' используется, чтобы указать поле документа для поиска. Если она опущена, то используется поле 'contents'.

или

Построение запроса через программный интерфейс:

<?php
$query = new Zend_Search_Lucene_Search_Query_MultiTerm();

$query->addTerm(new Zend_Search_Lucene_Index_Term('word1'), true);
$query->addTerm(new Zend_Search_Lucene_Index_Term('word2'), null);
$query->addTerm(new Zend_Search_Lucene_Index_Term('word3'), false);

$hits  = $index->find($query);

Массив $signs содержит информацию о типах элементов:

  • true используется для определения обязательных элементов.

  • false используется для определения запрещенных элементов.

  • null используется для определения необязательных элементов.

27.5.4. Фразовый запрос

Фразовые запросы предназначены для поиска по фразам.

Фразовые запросы являются очень гибкими и позволяют искать как точные фразы, так и неточные.

Фразы могут содержать пропуски или несколько слов в одной и той же позиции. (Это может быть сгенерировано анализатором для различных целей. Например, элементы могут повторяться для повышения "веса" или в одной позиции могут быть размещены несколько синонимов). В соответствии с этим фразовые запросы могут строиться только через программный интерфейс:

<?php
$query1 = new Zend_Search_Lucene_Search_Query_Phrase();

// Добавление 'word1' в относительную позицию 0.
$query1->addTerm(new Zend_Search_Lucene_Index_Term('word1'));

// Добавление 'word2' в относительную позицию 1.
$query1->addTerm(new Zend_Search_Lucene_Index_Term('word2'));

// Добавление 'word3' в относительную позицию 3.
$query1->addTerm(new Zend_Search_Lucene_Index_Term('word3'), 3);

...

$query2 = new Zend_Search_Lucene_Search_Query_Phrase(
                array('word1', 'word2', 'word3'), array(0,1,3));

...

// Запрос без промежутков.
$query3 = new Zend_Search_Lucene_Search_Query_Phrase(
                array('word1', 'word2', 'word3'));

...

$query4 = new Zend_Search_Lucene_Search_Query_Phrase(
                array('word1', 'word2'), array(0,1), 'annotation');

Фразовый запрос может строиться сразу с помощью конструктора класса или пошагово с помощью метода Zend_Search_Lucene_Search_Query_Phrase::addTerm().

Конструктор класса Zend_Search_Lucene_Search_Query_Phrase принимает три необязательных параметра:

<?php
Zend_Search_Lucene_Search_Query_Phrase([array $terms[, array $offsets[, string $field]]]);

$terms является массивом строк, который содержит набор элементов фразы. Если он опущен или равен null, то строится пустой запрос.

$offsets является массивом целочисленных значений, который содержит смещения элементов во фразе. Если он опущен или равен null, то позиции элементов предполагаются как array(0, 1, 2, 3, ...).

$field является строкой, которая указывает поле документа, в котором производится поиск. Если он опущен или равен null, то поиск производится в поле по умолчанию. Данная версия Zend_Search_Lucene трактует поле 'contents' как поле, выбираемое по умолчанию, но в следующих версиях планируется добавить возможность указания любого поля, как выбираемого по умолчанию.

Таким образом:

<?php
$query = new Zend_Search_Lucene_Search_Query_Phrase(array('zend', 'framework'));

будет искать фразу 'zend framework'.

<?php
$query = new Zend_Search_Lucene_Search_Query_Phrase(array('zend', 'download'), array(0, 2));

будет искать фразу 'zend ????? download', такой запрос соответствует фразам 'zend platform download', 'zend studio download', 'zend core download', 'zend framework download' и т.д.

<?php
$query = new Zend_Search_Lucene_Search_Query_Phrase(array('zend', 'framework'), null, 'title');

будет искать фразу 'zend framework' в поле 'title'.

Метод Zend_Search_Lucene_Search_Query_Phrase::addTerm() принимает два аргумента — объект элемента Zend_Search_Lucene_Index_Term в качестве обязательного параметра и позицию элемента в качестве необязательного:

<?php
Zend_Search_Lucene_Search_Query_Phrase::addTerm(Zend_Search_Lucene_Index_Term $term[, integer $position]);

$term описывает следующий элемент во фразе. Он должен указывать на то же самое поле, что и предыдущие элементы, иначе будет сгенерировано исключение.

$position указывает позицию элемента.

<?php
$query = new Zend_Search_Lucene_Search_Query_Phrase();
$query->addTerm(new Zend_Search_Lucene_Index_Term('zend'));
$query->addTerm(new Zend_Search_Lucene_Index_Term('framework'));

будет искать фразу 'zend framework'.

<?php
$query = new Zend_Search_Lucene_Search_Query_Phrase();
$query->addTerm(new Zend_Search_Lucene_Index_Term('zend'), 0);
$query->addTerm(new Zend_Search_Lucene_Index_Term('framework'), 2);

будет искать фразу 'zend ????? download', такой запрос соответствует фразам 'zend platform download', 'zend studio download', 'zend core download', 'zend framework download' и т.д.

<?php
$query = new Zend_Search_Lucene_Search_Query_Phrase();
$query->addTerm(new Zend_Search_Lucene_Index_Term('zend', 'title'));
$query->addTerm(new Zend_Search_Lucene_Index_Term('framework', 'title'));

будет искать фразу 'zend framework' в поле 'title'.

Коэффициент расстояния устанавливает допустимое количество других слов, находящихся между словами во фразе запроса. Если он равен нулю, то ищется точная фраза. При бОльших значениях это будет работать как оператор WITHIN или NEAR

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

Более точные соответствия имеют бОльшую релевантность, чем менее точные, таким образом, результаты сортируются по точности. По умолчанию коэффициент расстояния равен нулю, что означает точное соответствие.

Коэффициент расстояния может быть указан после создания запроса:

<?php
// Запрос без пропусков.
$query = new Zend_Search_Lucene_Search_Query_Phrase(array('word1', 'word2'));

// Поиск 'word1 word2', 'word1 ... word2'
$query->setSlop(1);
$hits1 = $index->find($query);

// Поиск 'word1 word2', 'word1 ... word2',
// 'word1 ... ... word2', 'word2 word1'
$query->setSlop(2);
$hits2 = $index->find($query);