我正在使用Lucene.NET 4.8-beta00005。
我在文档中有一个“名称”字段,定义如下:
doc.Add(CreateField(NameField, entry.Name.ToLower()));
writer.AddDocument(doc);
CreateField
的实现方式如下
private static Field CreateField(string fieldName, string fieldValue)
{
return new Field(fieldName, fieldValue, new FieldType() {IsIndexed = true, IsStored = true, IsTokenized = true, StoreTermVectors = true, StoreTermVectorPositions = true, StoreTermVectorOffsets = true, StoreTermVectorPayloads = true});
}
为“名称”字段分配了StandardAnalyzer
。
然后在我的CustomScoreProvider
中,从术语向量中检索这些术语,如下所示:
private List<string> GetDocumentTerms(int doc, string fieldName)
{
var indexReader = m_context.Reader;
var termVector = indexReader.GetTermVector(doc, fieldName);
var termsEnum = termVector.GetIterator(null);
BytesRef termBytesRef;
termBytesRef = termsEnum.Next();
var documentTerms = new List<string>();
while (termBytesRef != null)
{
//removing trailing \0 (padded to 16 bytes)
var termText = Encoding.Default.GetString(termBytesRef.Bytes).Replace("\0", "");
documentTerms.Add(termText);
termBytesRef = termsEnum.Next();
}
return documentTerms;
}
现在我有一个文档,其中“名称”字段的值是“ dan gertler diamonds ltd。”。
所以我期望的术语向量是:
丹·格特勒钻石有限公司
但是我的GetDocumentTerms
给我以下术语:
dan diamonds gertlers ltdtlers
我在该字段中用作StandardAnalyzer
,所以我不希望它对字段中的原始单词进行太多转换(并且我确实使用此特定名称和StandardAnalyzer进行了检查)。
我在这里做错什么以及如何解决?
编辑:我正在用每个字段的分析器手动扩展这些术语,并将它们作为单独的字符串存储在单独的String字段中。
答案 0 :(得分:1)
如果要以正确的顺序获取条款,则还必须使用位置信息。测试此代码:
Terms terms = indexReader.GetTermVector(doc, fieldName);
if (terms != null)
{
var termIterator = terms.GetIterator(null);
BytesRef bytestring;
var documentTerms = new List<Tuple<int, string>>();
while ((bytestring = termIterator.Next()) != null)
{
var docsAndPositions = termIterator.DocsAndPositions(null, null, DocsAndPositionsFlags.OFFSETS);
docsAndPositions.NextDoc();
int position;
for(int left = docsAndPositions.Freq; left > 0; left--)
{
position = docsAndPositions.NextPosition();
documentTerms.Add(new Tuple<int, string>(position, bytestring.Utf8ToString()));
}
}
documentTerms.Sort((word1, word2) => word1.Item1.CompareTo(word2.Item1));
foreach (var word in documentTerms)
{
Console.WriteLine("{0} {1} {2}", fieldName, word.Item1, word.Item2);
}
}
此代码还可以处理在多个地方使用相同术语(单词)的情况。