Lucene: подсчет очков с помощью PrefixQuery - PullRequest
8 голосов
/ 17 июня 2010

У меня проблема с подсчетом очков с помощью PrefixQuery. Чтобы изменить счет каждого документа, при добавлении документа в индекс я использовал setBoost, чтобы изменить усиление документа. Затем я создаю PrefixQuery для поиска, но результат не был изменен в соответствии с повышением. Кажется, setBoost полностью не работает для 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"));
    }
} 

Вывод:

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

Ответы [ 3 ]

11 голосов
/ 17 июня 2010

По умолчанию PrefixQuery переписывает запрос для использования ConstantScoreQuery, что дает каждому отдельному документу оценку 1,0.Я думаю, что это сделать PrefixQuery быстрее.Поэтому ваши повышения игнорируются.

Если вы хотите, чтобы усиления вступили в силу в вашем PrefixQuery, вам нужно вызвать setRewriteMethod (), используя константу SCORING_BOOLEAN_QUERY_REWRITE в вашем экземпляре запроса префикса.См. http://lucene.apache.org/java/2_9_1/api/all/index.html.

Для отладки вы можете использовать searcher.explain ().

2 голосов
/ 17 июня 2010

Это ожидаемое поведение.Вот объяснение Doug Cutting создателя Lucene:

Запрос PrefixQuery эквивалентен запросу, содержащему все термины, соответствующие префиксу, и, следовательно, обычно содержит много терминов.При таком большом запросе соответствующие документы, вероятно, будут содержать меньше условий запроса, и, следовательно, соответствие будет слабее.

Прочитать исходное сообщение , откуда берется цитата.

В Lucene, как правило, лучше использовать оценку только как относительную меру релевантности.в комплекте документов.Абсолютное значение оценки будет изменяться в зависимости от многих факторов, поэтому ее не следует использовать как есть.

ОБНОВЛЕНИЕ
В объяснении Cutting содержится ссылка на более старую версию Lucene.Таким образом, ответ от bajafresh4life является правильным.

0 голосов
/ 04 февраля 2015

Изменение метода перезаписи

Bajafresh4life предложил позвонить setRewriteMethod.Однако, это не то, как вы меняете это в Lucene.Net.Вот как это сделать в C #:

По умолчанию каждый PrefixQuery возвращается методом NewPrefixQuery из QueryParser примерно так:

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

Вы можете изменить это послесоздание экземпляра вашего синтаксического анализатора с помощью свойства set QueryParser.MultiTermRewriteMethod, например:

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

Обратите внимание, что это изменит поведение и для других запросов, а не только для запроса префикса.Чтобы повлиять только на запрос префикса, вы можете создать подкласс QueryParser и переопределить NewPrefixQuery, чтобы конструктор для возвращенного PrefixQuery использовал выбранный вами метод перезаписи.

Какой метод перезаписи использовать

Это, кажется, не исправило это для меня, хотя.Мне на самом деле повезло больше, используя MultiTermQuery.CONSTANT_SCORE_BOOLEAN_QUERY_REWRITE.В описании этого метода написано

Как и SCORING_BOOLEAN_QUERY_REWRITE, за исключением того, что баллы не вычисляются.Вместо этого каждый соответствующий документ получает постоянную оценку, равную ускорению запроса.

Но это может быть потому, что я также подклассифицировал PrefixQuery и переопределил ReWrite, чтобы назначить оценки, которые я хочу увеличить.

После значительной отладки я в конце концов понял, что, пытаясь использовать SCORING_BOOLEAN_QUERY_REWRITE, DefaultSimilarity.QueryNorm мешал моим оценкам, когда возвращаемое значение используется в Weight.Normalize, чтопозвонил Query.Weight.

...