2009-11-04 7 views
4

J'ai un problème avec la fonction de notation de Lucene que je n'arrive pas à comprendre. Jusqu'à présent, j'ai pu écrire ce code pour le reproduire.Problème avec la notation Lucene

package lucenebug; 

import java.util.Arrays; 
import java.util.List; 

import org.apache.lucene.analysis.SimpleAnalyzer; 
import org.apache.lucene.document.Document; 
import org.apache.lucene.document.Field; 
import org.apache.lucene.index.IndexWriter; 
import org.apache.lucene.queryParser.QueryParser; 
import org.apache.lucene.search.IndexSearcher; 
import org.apache.lucene.search.Query; 
import org.apache.lucene.search.ScoreDoc; 
import org.apache.lucene.search.TopDocs; 

public class Test { 
    private static final String TMP_LUCENEBUG_INDEX = "/tmp/lucenebug_index"; 

    public static void main(String[] args) throws Throwable { 
     SimpleAnalyzer analyzer = new SimpleAnalyzer(); 
     IndexWriter w = new IndexWriter(TMP_LUCENEBUG_INDEX, analyzer, true); 
     List<String> names = Arrays 
       .asList(new String[] { "the rolling stones", 
         "rolling stones (karaoke)", 
         "the rolling stones tribute", 
         "rolling stones tribute band", 
         "karaoke - the rolling stones" }); 
     try { 
      for (String name : names) { 
       System.out.println("#name: " + name); 
       Document doc = new Document(); 
       doc.add(new Field("name", name, Field.Store.YES, 
         Field.Index.TOKENIZED)); 
       w.addDocument(doc); 
      } 
      System.out.println("finished adding docs, total size: " 
        + w.docCount()); 

     } finally { 
      w.close(); 
     } 

     IndexSearcher s = new IndexSearcher(TMP_LUCENEBUG_INDEX); 
     QueryParser p = new QueryParser("name", analyzer); 
     Query q = p.parse("name:(rolling stones)"); 
     System.out.println("--------\nquery: " + q); 

     TopDocs topdocs = s.search(q, null, 10); 
     for (ScoreDoc sd : topdocs.scoreDocs) { 
      System.out.println("" + sd.score + "\t" 
        + s.doc(sd.doc).getField("name").stringValue()); 
     } 
    } 
} 

La sortie que je reçois de l'exécuter est:

finished adding docs, total size: 5 
-------- 
query: name:rolling name:stones 
0.578186 the rolling stones 
0.578186 rolling stones (karaoke) 
0.578186 the rolling stones tribute 
0.578186 rolling stones tribute band 
0.578186 karaoke - the rolling stones 

Je ne peux pas comprendre pourquoi the rolling stones a la même pertinence que the rolling stones tribute. Selon documentation de lucene, plus un champ a de jetons, plus le facteur de normalisation devrait être petit, et donc the rolling stones tribute devrait avoir un score inférieur à the rolling stones.

Des idées?

+0

Quelle version de Lucene utilisez-vous (vous liez le document API de 2.4)? Dans Lucene 2.9, les scores ne sont pas retournés par défaut, vous devez fournir un TopFieldCollector: http://www.gossamer-threads.com/lists/lucene/java-user/86309 – digitalarbeiter

+0

@gossamer: J'ai exécuté le même code contre Lucene 2.3, 2.4 et 2.9. Mêmes résultats –

Répondre

5

Le facteur de normalisation de la longueur est calculée comme 1/sqrt(numTerms) (Vous pouvez voir cela dans DefaultSimilarity

Ce résultat n'est pas stocké dans l'index directement. Cette valeur est multipliée par la valeur de boost pour le champ spécifié. Le résultat final est puis codé sur 8 bits comme expliqué dans Similarity.encodeNorm() Ceci est un codage avec perte, ce qui signifie que les détails fins se perdent.

Si vous voulez voir la normalisation de la longueur en action, essayez de créer document avec la phrase suivante.

the rolling stones tribute a b c d e f g h i j k 

Cela créera une différence suffisante dans les valeurs de normalisation de longueur que vous pourriez voir.

Maintenant, si votre domaine ont très peu de jetons que par les exemples que vous avez utilisés, vous pouvez définir des valeurs d'amplification pour les documents/champs en fonction de votre propre formule qui est essentiellement coup de pouce supérieur pour le champ court. Vous pouvez également créer une similarité personnalisée et remplacer la méthode legthNorm().

+0

C'est vrai, l'encodage 8 bits arrondissait le 'boost * lengthNorm' et causait le problème. Définir l'augmentation de champ à 100 pendant l'indexation est une solution de contournement assez propre pour moi. @Shashikant Kore Merci! –

0

Je peux le reproduire sur Lucene 2.3.1 mais je ne sais pas pourquoi cela se produit.

Questions connexes