Проблема с Lucene - поиск не индексирует числовые значения? - PullRequest
4 голосов
/ 17 марта 2009

Я использую Lucene в PHP (используя реализацию Zend Framework). У меня проблема с тем, что я не могу найти поле, содержащее число.

Вот данные в индексе:

      ts      |    contents
--------------+-----------------
  1236917100  | dog cat gerbil
  1236630752  |  cow pig goat
  1235680249  | lion tiger bear
  nonnumeric  | bass goby trout

Моя проблема : запрос "ts:1236630752" не возвращает результатов. Однако запрос «ts:nonnumeric» возвращает попадание.

Я храню "ts" в качестве ключевого поля, которое в соответствии с документацией"не маркируется, но индексируется и хранится. Полезно для нетекстовых полей, например, date или url." Я пытался трактовать его как текстовое поле, но поведение такое же, за исключением того, что запрос "ts:*" ничего не возвращает, когда ts является текстом.

Я использую Zend Framework 1.7 (только что скачанную последние 3 дня назад) и PHP 5.2.9. Вот мой код:

<?php

//=========================================================
// Initializes Zend Framework (Zend_Loader).
//=========================================================
set_include_path(realpath('../library') . PATH_SEPARATOR . get_include_path());
require_once('Zend/Loader.php');
Zend_Loader::registerAutoload();

//=========================================================
// Delete existing index and create a new one
//=========================================================
define('SEARCH_INDEX', 'test_search_index');
if(file_exists(SEARCH_INDEX))
  foreach(scandir(SEARCH_INDEX) as $file)
    if(!is_dir($file))
      unlink(SEARCH_INDEX . "/$file");

$index = Zend_Search_Lucene::create(SEARCH_INDEX);

//=========================================================
// Create this data in index:
//         ts      |    contents
//   --------------+-----------------
//     1236917100  | dog cat gerbil
//     1236630752  |  cow pig goat
//     1235680249  | lion tiger bear
//     nonnumeric  | bass goby trout
//=========================================================

function add_to_index($index, $ts, $contents) {
  $doc = new Zend_Search_Lucene_Document();
  $doc->addField(Zend_Search_Lucene_Field::Keyword('ts', $ts));
  $doc->addField(Zend_Search_Lucene_Field::Text('contents', $contents));
  $index->addDocument($doc);
}

add_to_index($index, '1236917100', 'dog cat gerbil');
add_to_index($index, '1236630752', 'cow pig goat');
add_to_index($index, '1235680249', 'lion tiger bear');
add_to_index($index, 'nonnumeric', 'bass goby trout');

//=========================================================
// Run some test queries and output results
//=========================================================

echo '<html><body><pre>';

function run_query($index, $query) {
  echo "Running query:  $query\n";
  $hits = $index->find($query);
  echo 'Got ' . count($hits) . " hits.\n";
  foreach($hits as $hit)
    echo "  ts='$hit->ts', contents='$hit->contents'\n";
  echo "\n";
}

run_query($index, 'pig');           //1 hit
run_query($index, 'ts:1236630752'); //0 hits
run_query($index, '1236630752');    //0 hits
run_query($index, 'ts:pig');        //0 hits
run_query($index, 'contents:pig');  //1 hits
run_query($index, 'ts:[1236630700 TO 1236630800]'); //0 hits (range query)
run_query($index, 'ts:*');          //4 hits if ts is keyword, 1 hit otherwise
run_query($index, 'nonnumeric');    //1 hits
run_query($index, 'ts:nonnumeric'); //1 hits
run_query($index, 'trout');         //1 hits

выход

Running query:  pig
Got 1 hits.
  ts='1236630752', contents='cow pig goat'

Running query:  ts:1236630752
Got 0 hits.

Running query:  1236630752
Got 0 hits.

Running query:  ts:pig
Got 0 hits.

Running query:  contents:pig
Got 1 hits.
  ts='1236630752', contents='cow pig goat'

Running query:  ts:[1236630700 TO 1236630800]
Got 0 hits.

Running query:  ts:*
Got 4 hits.
  ts='1236917100', contents='dog cat gerbil'
  ts='1236630752', contents='cow pig goat'
  ts='1235680249', contents='lion tiger bear'
  ts='nonnumeric', contents='bass goby trout'

Running query:  nonnumeric
Got 1 hits.
  ts='nonnumeric', contents='bass goby trout'

Running query:  ts:nonnumeric
Got 1 hits.
  ts='nonnumeric', contents='bass goby trout'

Running query:  trout
Got 1 hits.
  ts='nonnumeric', contents='bass goby trout'

Ответы [ 3 ]

4 голосов
/ 17 марта 2009

Метод find () маркирует запрос, и при использовании анализатора по умолчанию ваши числа будут в значительной степени игнорироваться. Если вы хотите найти число, вам нужно создать запрос или использовать альтернативный анализатор , который содержит числовые значения ..

http://framework.zend.com/manual/en/zend.search.lucene.searching.html

Важно отметить, что Парсер запросов использует стандарт анализатор для токенизации отдельных частей Строка запроса. Таким образом, все преобразования которые применяются к индексированному тексту также применяется к строкам запроса.

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

Метод API не трансформируется или фильтровать входные термины любым способом. Это поэтому больше подходит для компьютера сгенерированные или неотмеченные поля.

2 голосов
/ 17 марта 2009

Я привык использовать Lucene под Java, поэтому не могу сказать, верен ли ваш код, но похоже, что поле токанизируется таким образом, что удаляет что-либо, кроме [a-zA-Z].

Это может помочь пролить свет на ситуацию, используя инструмент проводника индекса, такой как http://www.getopt.org/luke/, чтобы точно увидеть, что находится в индексе.

0 голосов
/ 09 января 2013

Мне удалось довольно легко получить текст и цифры, используя Zend / Search / Lucene / Analysis / Analyzer / Common / TextNum.php в качестве значения по умолчанию (используйте :: setDefault (...), как описано выше.

Моя проблема в том, что я пытался проиндексировать большой набор программного и аппаратного обеспечения с длинной историей и многими номерами версий. Zend Search Lucene не использовал токены для «слов», таких как «1.5.3» или чего-либо с точкой (IP-адреса, например), подчеркиванием или дефисом.

Сначала я сделал копию TextNum.php, переименовал в TextNumSSC.php (SSC - название нашего приложения) и попытался отредактировать RegEx:

do {
                 if (! preg_match('/[a-zA-Z0-9.-_]+/', $this->_input, $match, PREG_OFFSET_CAPTURE, $this->_position)) { 
                     // It covers both cases a) there are no matches (preg_match(...) === 0)
                     // b) error occured (preg_match(...) === FALSE)
                     return null;
                 }

Все еще не повезло.

Затем я установил http://codefury.net/projects/StandardAnalyzer/ в соответствии с указаниями, за пределами структуры каталогов Zend, изменил RegEx на

'/[a-zA-Z0-9.-_]+/'

и теперь это работает.

Не уверен, что это является основной причиной, но не смог найти что-либо в SO или сети для решения этой проблемы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...