2009-03-17 2 views
3

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

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

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

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

Я сохраняю «ts» в качестве поля ключевого слова, которое according to documentation «не является токеном, а индексируется и сохраняется. Полезно для нетекстовых полей, например, даты или 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

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

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

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

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

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

+0

Обратите внимание, что новые версии Zend Search Lucene включают алфавитно-цифровой анализатор; вам просто нужно установить его как значение по умолчанию. Обязательно включите это рядом с началом вашего скрипта индексирования, а также перед запуском $ index-> ​​find(): Zend_Search_Lucene_Analysis_Analyzer :: setDefault (новый Zend_Search_Lucene_Analysis_Analyzer_Common_TextNum_CaseInsensitive()); –

2

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

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

0

Я был в состоянии получить текст и номера довольно легко с помощью Zend/Search/Lucene/Анализ/анализатор/Common/TextNum.php по умолчанию (использование :: SetDefault (...), как описано выше.

Моя проблема в том, что я пытался индексировать большой набор программного и аппаратного обеспечения с длинной историей и многими номерами версий. Zend Поиск 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 или в Интернете, чтобы решить эту проблему.

Смежные вопросы