У меня есть решение для этого с использованием Lucene.Net 3.0.3 и полезной нагрузки. Я не уверен, что это лучший способ сделать это, используя java-версию, которая в настоящее время немного опережает порт .net.
Он работает путем назначения полезной нагрузки, пользовательского массива байтов терминам, которые должны быть оценены пользователем, и пользовательского сходства, которое переопределяет ScorePayload для анализа массива байтов для выполнения пользовательской фильтрации. (для этого потребуется запрос, вызывающий этот метод, например PayloadTermQuery).
Этот чрезвычайно надуманный пример кода будет оценивать термин на основе (id % 3). (Число, кратное трем, оценивается как ноль). Вы можете использовать это в сочетании с PositiveScoresOnlyCollector, чтобы игнорировать совпадения, получившие нулевой балл.
using System;
using System.IO;
using Lucene.Net.Analysis;
using Lucene.Net.Analysis.Tokenattributes;
using Lucene.Net.Documents;
using Lucene.Net.Index;
using Lucene.Net.Search;
using Lucene.Net.Search.Payloads;
using Lucene.Net.Store;
public static class Program {
public static void Main() {
var directory = new RAMDirectory();
// Initialization; create 50 documents with payload
var writer = new IndexWriter(directory, new KeywordAnalyzer(), true, IndexWriter.MaxFieldLength.UNLIMITED);
for (var i = 0; i < 50; ++i) {
AddDocument(writer, i, "lorem ipsum etc blah blah");
}
writer.Commit();
var searcher = new IndexSearcher(directory, readOnly: true);
searcher.Similarity = new ShazaamPayloadSimilarity();
// The term we'll be looking for. This should match all documents.
var term = new Term("Data", "lorem");
var query = new PayloadTermQuery(term, new MaxPayloadFunction());
var topDocs = searcher.Search(query, 40);
// This is a bad example of a FieldCache usage.
var iValues = FieldCache_Fields.DEFAULT.GetStrings(searcher.IndexReader, "Id");
foreach (var scoreDoc in topDocs.ScoreDocs) {
Console.WriteLine("Score: {0:0.0000} i={1}", scoreDoc.Score, iValues[scoreDoc.Doc]);
}
Console.ReadLine();
}
public static void AddDocument(IndexWriter writer, Int32 id, String data) {
var payload = BitConverter.GetBytes(id);
var analyzer = new ShazaamPayloadAnalyzer(payload);
var textReader = new StringReader(data);
var document = new Document();
document.Add(new Field("Id", id.ToString(), Field.Store.NO, Field.Index.NOT_ANALYZED));
document.Add(new Field("Data", analyzer.TokenStream(null, textReader)));
writer.AddDocument(document);
}
}
public class ShazaamPayloadAnalyzer : Analyzer {
private readonly Byte[] _value;
public ShazaamPayloadAnalyzer(Byte[] value) {
_value = value;
}
public override TokenStream TokenStream(String fieldName, TextReader reader) {
TokenStream result = new WhitespaceTokenizer(reader);
result = new ShazaamPayloadFilter(result, _value);
return result;
}
}
public class ShazaamPayloadFilter : TokenFilter {
private readonly byte[] _payload;
private readonly IPayloadAttribute _payloadAttr;
public ShazaamPayloadFilter(TokenStream input, Byte[] payload)
: base(input) {
_payload = payload;
_payloadAttr = AddAttribute<IPayloadAttribute>();
}
public override Boolean IncrementToken() {
if (input.IncrementToken()) {
_payloadAttr.Payload = new Payload(_payload);
return true;
}
return false;
}
}
public class ShazaamPayloadSimilarity : DefaultSimilarity {
public override Single ScorePayload(Int32 docId, String fieldName, Int32 start, Int32 end, Byte[] payload, Int32 offset, Int32 length) {
var originalValue = BitConverter.ToInt32(payload, startIndex: 0);
// Advanced logic ahead!
return (originalValue % 3);
}
}
person
sisve
schedule
02.12.2013