Я хочу использовать Lucene со следующей логикой скоринга: Когда я индексирую свои документы, я хочу установить для каждого поля балл / вес.Когда я запрашиваю свой индекс, я хочу установить для каждого термина запроса оценку / вес.
Я НИКОГДА не буду индексировать или выполнять запрос со многими экземплярами одного и того же поля - в каждом запросе (документе) будет 0-1экземпляры с тем же именем поля.Мои поля / термин запроса не анализируются - они уже составлены из одного токена.
Я хочу, чтобы оценка была просто точечным произведением между полями запроса и полями документа, если они имеютто же значение.
Например:
Формат (Имя поля) (Значение поля) (Оценка поля)
Запрос:
1 AA 0.1
7 BB 0.2
8CC 0,3
Документ 1:
1 AA 0,2
2 DD 0,8
7 CC 0,999
10 FFF 0,1
Документ 2:
7 BB 0,3
8 CC 0,5
Баллы должны быть:
Оценка (q, d1) = FIELD_1_SCORE_Q * FILED_1_SCORE_D1 = 0,1 * 0,2 = 0,02
Оценка (q, d2) = FIELD_7_SCORE_Q * FILED_7_SCORE_D2 + FIELD_8_SCORE_Q * FILED_8_SCORE_D2 = (0,2 * 0,3) + (0,3 * 0,5)
Как лучше всего это реализовать?С точки зрения точности и производительности (мне не нужны вычисления TF и IDF).
В настоящее время я реализовал это, установив повышение для полей и условий запроса.Затем я перезаписываю класс DefaultSogeneity и устанавливаю его по умолчанию перед индексацией / запросом:
public class MySimilarity extends DefaultSimilarity {
@Override
public float computeNorm(String field, FieldInvertState state) {
return state.getBoost();
}
@Override
public float queryNorm(float sumOfSquaredWeights) {
return 1;
}
@Override
public float tf(float freq) {
return 1;
}
@Override
public float idf(int docFreq, int numDocs) {
return 1;
}
@Override
public float coord(int overlap, int maxOverlap) {
return 1;
}
}
И на основе http://lucene.apache.org/core/old_versioned_docs/versions/3_5_0/scoring.html это должно работать.
Проблемы:
- Исполнения: Я вычисляю все вещи TF / IDF и NORMS впустую…
- Оценка, которую я получаю от TopScoreDocCollector, отличается от оценки, полученной из объяснения.
Вот часть моего кода:
indexSearcher = new IndexSearcher(IndexReader.open(directory, true));
TopScoreDocCollector collector = TopScoreDocCollector.create(iTopN, true);
indexSearcher.search(query, collector);
ScoreDoc[] hits = collector.topDocs().scoreDocs;
for (int i = 0; i < hits.length; ++i) {
int docId = hits[i].doc;
Document d = indexSearcher.doc(docId);
double score = hits[i].score;
String id = d.get(FIELD_ID);
Explanation explanation = indexSearcher.explain(query, docId);
}
Спасибо!