2010-06-17 15 views
8

Tengo un problema con el cálculo de puntaje con PrefixQuery. Para cambiar el puntaje de cada documento, cuando agrego el documento al índice, he usado setBoost para cambiar el impulso del documento. Luego creo PrefixQuery para buscar, pero el resultado no se ha modificado de acuerdo con el impulso. Parece que setBoost no funciona para PrefixQuery. Por favor, compruebe el código de abajo:Lucene: cálculo de puntaje con 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")); 
    } 
} 

La salida es:

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

Respuesta

2

Es el comportamiento esperado. Aquí está la explicación de Doug Cutting de Lucene creador:

Un PrefixQuery es equivalente a una consulta que contenga todos los términos que coinciden con el prefijo , y es por lo tanto, por lo general contiene una gran cantidad de términos. Con una consulta tan grande , es probable que los documentos coincidentes contengan menos términos de consulta y la coincidencia es, por lo tanto, más débil.

Lea the original post de donde está tomando la cita.

Con Lucene, generalmente es mejor usar la puntuación solo como una medida relativa de la relevancia en un conjunto de documentos. El valor absoluto de la puntuación cambiará en función de tantos factores que no debería utilizarse tal cual.

ACTUALIZACIÓN
La explicación de corte se refiere a una versión anterior de Lucene. Por lo tanto, la respuesta de bajafresh4life es la correcta.

11

De forma predeterminada, PrefixQuery reescribe la consulta para usar ConstantScoreQuery, que otorga a cada documento coincidente una puntuación de 1.0. Creo que esto es para hacer PrefixQuery más rápido. Entonces tus impulsos son ignorados.

Si desea que los refuerzos surtan efecto en su PrefixQuery, debe llamar a setRewriteMethod(), utilizando la constante SCORING_BOOLEAN_QUERY_REWRITE en su instancia de consulta de prefijo. Ver http://lucene.apache.org/java/2_9_1/api/all/index.html.

Para la depuración, puede utilizar searcher.explain().

+0

Tenga en cuenta que esto también parece aplicarse cuando se usa setBoost en un nivel de campo. es decir, PrefixQuery parecerá ignorar los aumentos de campo a menos que cambie el método de reescritura como se describe aquí. –

+0

esto me ayudó, por favor marque como la respuesta. – fommil

0

Cambio del reescribir método

Bajafresh4life sugirió llamar setRewriteMethod. Sin embargo, esa no es la forma de cambiar esto en Lucene.Net. He aquí cómo hacerlo en C#:

Por defecto, cada PrefixQuery es devuelto por el método NewPrefixQuery de QueryParser así:

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

Usted puede cambiar esto después de crear instancias de su programa de análisis mediante la propiedad set de QueryParser.MultiTermRewriteMethod , como tal:

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

Tenga en cuenta que esto también cambiará el comportamiento de otras consultas, no solo la consulta de prefijo.Para afectar solo a la consulta de prefijo, puede crear la subclase QueryParser e invalidar NewPrefixQuery para que el constructor del PrefixQuery devuelto utilice el método de reescritura de su elección.

Qué reescribir método para utilizar

que no parece que se han fijado para mí, sin embargo. De hecho, tuve suerte usando MultiTermQuery.CONSTANT_SCORE_BOOLEAN_QUERY_REWRITE. En la descripción de este método, dice

Me gusta SCORING_BOOLEAN_QUERY_REWRITE excepto que los puntajes no se computan. En cambio, cada documento coincidente recibe una puntuación constante igual al impulso de la consulta.

pero que podría ser porque yo también subclases PrefixQuery y ReWrite hizo caso omiso de asignar los puntajes que quiero como refuerzos.

Después de una buena cantidad de depuración, al final me di cuenta de que, mientras yo estaba tratando de usar SCORING_BOOLEAN_QUERY_REWRITE, DefaultSimilarity.QueryNorm estaba interfiriendo con mis resultados cuando el valor que devuelve se utiliza en Weight.Normalize, que se llama en Query.Weight.

Cuestiones relacionadas