2010-06-17 3 views
8

Ich habe ein Problem mit der Score-Berechnung mit einer PrefixQuery. Um das Ergebnis jedes Dokuments zu ändern, habe ich beim Hinzufügen eines Dokuments in den Index setBoost verwendet, um den Boost des Dokuments zu ändern. Dann erstelle ich PrefixQuery für die Suche, aber das Ergebnis wurde nicht entsprechend dem Boost geändert. Es scheint, dass setBoost bei einer PrefixQuery nicht funktioniert. Bitte überprüfen Sie meinen Code unten:Lucene: Score-Berechnung mit einer PrefixQuery

@Test 
public void testNormsDocBoost() throws Exception { 
    Directory dir = new RAMDirectory(); 
    IndexWriter writer = new IndexWriter(dir, new StandardAnalyzer(Version.LUCENE_CURRENT), true, 
      IndexWriter.MaxFieldLength.LIMITED); 
    Document doc1 = new Document(); 
    Field f1 = new Field("contents", "common1", Field.Store.YES, Field.Index.ANALYZED); 
    doc1.add(f1); 
    doc1.setBoost(100); 
    writer.addDocument(doc1); 
    Document doc2 = new Document(); 
    Field f2 = new Field("contents", "common2", Field.Store.YES, Field.Index.ANALYZED); 
    doc2.add(f2); 
    doc2.setBoost(200); 
    writer.addDocument(doc2); 
    Document doc3 = new Document(); 
    Field f3 = new Field("contents", "common3", Field.Store.YES, Field.Index.ANALYZED); 
    doc3.add(f3); 
    doc3.setBoost(300); 
    writer.addDocument(doc3); 
    writer.close(); 

    IndexReader reader = IndexReader.open(dir); 
    IndexSearcher searcher = new IndexSearcher(reader); 

    TopDocs docs = searcher.search(new PrefixQuery(new Term("contents", "common")), 10); 
    for (ScoreDoc doc : docs.scoreDocs) { 
     System.out.println("docid : " + doc.doc + " score : " + doc.score + " " 
       + searcher.doc(doc.doc).get("contents")); 
    } 
} 

Die Ausgabe lautet:

docid : 0 score : 1.0 common1 
docid : 1 score : 1.0 common2 
docid : 2 score : 1.0 common3 

Antwort

2

Es ist das erwartete Verhalten. Hier ist die Erklärung von Lucene Schöpfers Doug Cutting:

A PrefixQuery entspricht einer Abfrage alle Bedingungen, welche die Präfix übereinstimmt, und ist daher enthält in der Regel eine Menge von Begriffen. Bei einer so großen Abfrage enthalten übereinstimmende Dokumente wahrscheinlich weniger Suchbegriffe und die Übereinstimmung ist somit schwächer.

Gelesen the original post, wo das Zitat von nimmt.

Mit Lucene ist es im Allgemeinen besser, den Score nur als relatives Maß für die Relevanz in einer Reihe von Dokumenten zu verwenden. Der absolute Wert der Punktzahl ändert sich in Abhängigkeit von so vielen Faktoren, dass er nicht so verwendet werden sollte, wie er ist.

UPDATE
Die Erklärung von Cutting bezieht sich auf eine ältere Version von Lucene. Daher ist die Antwort von bajafresh4life die richtige.

11

Standardmäßig schreibt PrefixQuery die Abfrage so um, dass sie ConstantScoreQuery verwendet, wodurch jedem übereinstimmenden Dokument ein Wert von 1,0 zugewiesen wird. Ich denke, das ist PrefixQuery schneller zu machen. So werden Ihre Boosts ignoriert.

Wenn die Boosts in PrefixQuery wirksam werden sollen, müssen Sie setRewriteMethod() aufrufen, indem Sie die Konstante SCORING_BOOLEAN_QUERY_REWRITE für Ihre Präfixabfrage verwenden. Siehe http://lucene.apache.org/java/2_9_1/api/all/index.html.

Zum Debuggen können Sie searcher.explain() verwenden.

+0

Beachten Sie, dass dies auch bei Verwendung von setBoost in einer Feldebene zu gelten scheint. d. h. PrefixQuery scheint die Feldverstärkungen zu ignorieren, es sei denn, Sie ändern das Umschreibverfahren wie hier beschrieben. –

+0

das hat mir geholfen, bitte als Antwort markieren. – fommil

0

Ändern der Rewrite-Methode

Bajafresh4life Aufruf setRewriteMethod vorgeschlagen. Dies ändert sich jedoch nicht in Lucene.Net. Hier ist, wie es in C# tun:

standardmäßig jede PrefixQuery wird durch die NewPrefixQuery Methode von QueryParser wie so zurückgegeben:

protected internal virtual Query NewPrefixQuery(Term prefix) 
{ 
    return new PrefixQuery(prefix) { RewriteMethod = multiTermRewriteMethod }; 
} 

Sie können dies nach dem Parser ändern Instanziieren mithilfe der set Eigenschaft QueryParser.MultiTermRewriteMethod , wie folgt:

var parser = new QueryParser(Version.LUCENE_30, field, analyzer); 
parser.MultiTermRewriteMethod = MultiTermQuery.SCORING_BOOLEAN_QUERY_REWRITE; 

Beachten Sie, dass dies das Verhalten auch für andere Abfragen ändert, nicht nur für die Präfixabfrage.Um nur die Präfixabfrage zu beeinflussen, können Sie QueryParser untergliedern und NewPrefixQuery überschreiben, so dass der Konstruktor für das zurückgegebene PrefixQuery die Umschreibungsmethode Ihrer Wahl verwendet.

Welche Rewrite Methode

zu verwenden, die nicht es aber für mich festgelegt zu haben scheint. Ich hatte tatsächlich mehr Glück mit MultiTermQuery.CONSTANT_SCORE_BOOLEAN_QUERY_REWRITE. In der Beschreibung für diese Methode heißt es

Wie SCORING_BOOLEAN_QUERY_REWRITE mit Ausnahme von Scores werden nicht berechnet. Stattdessen erhält jedes übereinstimmende Dokument einen konstanten Wert, der dem Boost der Abfrage entspricht.

Aber das sein könnte, weil ich auch PrefixQuery subclassed und overrode ReWrite die Noten Ich will als Boosts zuweisen.

Nach einem fairen Betrag von Debugging, ich heraus, schließlich dachte, dass, während ich SCORING_BOOLEAN_QUERY_REWRITE zu verwenden versuchte, DefaultSimilarity.QueryNorm mit meinen Noten wurde zu stören, wenn der Wert wird in Weight.Normalize verwendet zurückgibt, die in Query.Weight genannt wird.