2009-03-17 5 views
3

J'utilise Lucene en PHP (en utilisant l'implémentation de Zend Framework). J'ai un problème que je ne peux pas rechercher sur un champ qui contient un nombre.Problème avec Lucene: la recherche n'indexe pas les valeurs numériques?

Voici les données de l'indice:

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

Mon problème: Une requête pour "ts:1236630752" renvoie pas de résultats. Cependant, une requête pour "ts:nonnumeric" renvoie un succès.

Je stocke "ts" en tant que champ de mot-clé, qui according to documentation "n'est pas segmenté, mais indexé et stocké, utile pour les champs non textuels, par exemple la date ou l'URL." J'ai essayé de le traiter comme un champ "texte", mais le comportement est le même sauf qu'une requête pour "ts:*" ne renvoie rien quand ts est du texte. J'utilise Zend Framework 1.7 (il y a juste 3 jours) et PHP 5.2.9. Voici mon code:

<?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 

Sortie

 
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' 

Répondre

3

La méthode find() marque la requête, et avec l'Analzer par défaut, vos numéros seront pratiquement ignorés. Si vous voulez rechercher un numéro que vous avez à construct the query ou utilisez un analyzer alternatif qui comprend des valeurs numériques ..

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

Il est important de noter que l'analyseur de requêtes utilise analyseur l' standard pour atomiser les parties séparées de la chaîne de requête . Ainsi toutes les transformations qui sont appliquées au texte indexé sont également appliquées aux chaînes de requête.

L'analyseur standard peut transformer la chaîne de requête en minuscules pour insensibilité à la casse, enlever stop-mots, et la tige entre autres transformations.

La méthode API ne transforme pas ou les termes d'entrée du filtre de quelque manière que ce soit. C'est donc plus approprié pour l'ordinateur champs générés ou non.

+0

Notez que les nouvelles versions de Zend Search Lucene incluent un analyseur alphanumérique; il vous suffit de le définir par défaut. Assurez-vous d'inclure ce près du début de votre script d'indexation ainsi que avant d'exécuter $ index-> ​​find(): Zend_Search_Lucene_Analysis_Analyzer :: setDefault (nouveau Zend_Search_Lucene_Analysis_Analyzer_Common_TextNum_CaseInsensitive()); –

2

Je suis habitué à utiliser Lucene sous Java je ne peux pas dire si votre code est correct, mais il semble que le champ est d'être tokanisé d'une manière qui dépouille tout sauf [a-zA-Z].

Cela peut aider à faire la lumière sur la situation à utiliser un outil d'exploration d'index comme http://www.getopt.org/luke/ pour voir exactement ce qui est dans l'index.

0

j'ai pu obtenir un texte et des chiffres assez facilement en utilisant Zend/Recherche/Lucene/Analyse/Analyseur/commune/TextNum.php par défaut (utilisation :: setDefault (...) comme décrit ci-dessus. Mon problème est que j'essayais d'indexer un grand nombre de logiciels et de matériel avec un long historique et de nombreux numéros de version Zend Search Lucene ne marquait pas des "mots" comme "1.5.3" ou quelque chose avec un point (Adresses IP, par exemple), soulignement ou trait d'union.

J'ai d'abord fait une copie de TextNum.php, rebaptisés TextNumSSC.php (SSC est notre nom de l'application) et essayé de modifier l'expression régulière:

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; 
       } 

Toujours pas de chance.

J'installé http://codefury.net/projects/StandardAnalyzer/ de la manière instruction, en dehors de la structure de répertoire Zend, a changé le RegEx à

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

et maintenant il fonctionne.

Vous n'êtes pas sûr de la cause première de ce problème, mais vous n'avez rien trouvé sur SO ou sur le Web pour résoudre ce problème.

Questions connexes