2010-12-02 43 views
0

Un petit résumé de mon problème, l'opérateur générique ne semble pas retourner le résultat que j'attends. Je suis en train de tester cela sur un champ Keyword.Zend_Lucene et l'étrangleur de l'opérateur wilcard

Voici venir un échantillon montrant la question

include 'Zend/Loader/Autoloader.php'; 
$autoloader = Zend_Loader_Autoloader::getInstance(); 
$autoloader->setFallbackAutoloader(true); 


Zend_Search_Lucene_Analysis_Analyzer::setDefault(
    new Zend_Search_Lucene_Analysis_Analyzer_Common_Utf8_CaseInsensitive()); 
@mkdir('/tmp/test-lucene'); 
$index = Zend_Search_Lucene::create('/tmp/test-lucene'); 
$doc = new Zend_Search_Lucene_Document(); 
$doc->addField(Zend_Search_Lucene_Field::Keyword('path', 'root/1/2/3')); 
$doc->addField(Zend_Search_Lucene_Field::UnStored('contents', 'The lazy fox jump over the dog bla bla bla')); 
$index->addDocument($doc); 


$doc = new Zend_Search_Lucene_Document(); 
$doc->addField(Zend_Search_Lucene_Field::Keyword('path', 'root/1')); 
$doc->addField(Zend_Search_Lucene_Field::UnStored('contents', 'The lazy fox jump over the dog bla bla bla')); 
$index->addDocument($doc); 

$doc = new Zend_Search_Lucene_Document(); 
$doc->addField(Zend_Search_Lucene_Field::Keyword('path', 'root/3/2/1')); 
$doc->addField(Zend_Search_Lucene_Field::UnStored('contents', 'The lazy fox jump over the dog bla bla bla')); 
$index->addDocument($doc); 

$doc = new Zend_Search_Lucene_Document(); 
$doc->addField(Zend_Search_Lucene_Field::Keyword('path', 'root/3/2/2')); 
$doc->addField(Zend_Search_Lucene_Field::UnStored('contents', 'The lazy fox jump over the dog bla bla bla')); 
$index->addDocument($doc); 

$hits = $index->find('path:root/3/2*'); 
foreach($hits as $hit){ 
    $doc = $hit->getDocument(); 
    echo $doc->getFieldValue('path') . PHP_EOL; 
} 

Cela renverra l'ensemble des documents au lieu des deux derniers comme je prévu

sortie:

root/1/2/3 
root/1 
root/3/2/1 
root/3/2/2 

Donc ici ma question pourquoi Lucene (Zend_Lucene dans ce cas) correspond aux premiers documents, je pensais que Keyword champs ne sont pas tokenized. PS: pour ceux qui voudraient savoir pourquoi je fais ce test. J'ai un site de commerce électronique avec une base de données, la table de catégorie a un champ de chemin. Par exemple une catégorie peut avoir ce chemin '/ 1/2/3' ce qui signifie que c'est la catégorie avec l'id 3 et la catégorie parent est l'index 2 etc ...

Le problème est quand un utilisateur fait une recherche plein texte et spécifier une catégorie, idéalement je veux retourner les résultats de cette catégorie mais aussi les catégories enfants, donc j'ai besoin d'une façon lucene de faire le chemin LIKE '/ 1/2%'.

Une autre possibilité serait de fusionner les résultats d'une requête SQL et des résultats lucene, si possible, je voudrais éviter ce cas, car il pourrait mal fonctionner.

Si vous avez des idées, vous êtes les bienvenus.

Répondre

1

Utilisez Zend_Search_Lucene_Analysis_Analyzer_Common_Utf8Num_CaseInsensitive et remplacez les barres obliques par un caractère qui n'apparaît pas dans vos chemins mais qui est un caractère de mot à Zend_Search_Lucene. J'ai utilisé allemand ß.

include 'Zend/Loader/Autoloader.php'; 
$autoloader = Zend_Loader_Autoloader::getInstance(); 
$autoloader->setFallbackAutoloader(true); 

Zend_Search_Lucene_Analysis_Analyzer::setDefault(
    new Zend_Search_Lucene_Analysis_Analyzer_Common_Utf8Num_CaseInsensitive()); 
@mkdir('/tmp/test-lucene'); 
$index = Zend_Search_Lucene::create('/tmp/test-lucene'); 

foreach (array('root/1/2/3', 'root/1', 'root/3/2/1', 'root/3/2/2') as $path) { 
    $path = str_replace('/', 'ß', $path); 
    $doc = new Zend_Search_Lucene_Document(); 
    $doc->addField(Zend_Search_Lucene_Field::Keyword('path', $path)); 
    $index->addDocument($doc); 
} 

$hits = $index->find(str_replace('/', 'ß', 'path:root/3/2*')); 
foreach($hits as $hit){ 
    echo str_replace('ß', '/', $hit->getDocument()->getFieldValue('path')) . PHP_EOL; 
} 
+0

Merci pour les réponses cela fonctionne. Je vois si lucene enlevait les chiffres à cause de l'analyseur. Après je ne peux pas vraiment expliquer pourquoi remplacer le/par une lettre de mot changer quelque chose, le champ Mot-clé ne devrait pas être tokenized droit? – RageZ

+0

Les champs de mot-clé ne sont pas segmentés, c'est vrai. Mais la requête de recherche est. – rik

+0

bon point, ça l'explique – RageZ