Правильное хранение / поиск termVector - PullRequest
0 голосов
/ 29 мая 2019

Я использую 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;
}

Теперь у меня есть документ, в котором значение поля "name" равно "dan gertler diamonds ltd."

Итак, термины из термина вектор, который я ожидаю, это:

Дэн Гертлер Даймондс Лтд

Но мой GetDocumentTerms дает мне следующие термины:

Дан Бриллианты Gertlers Ltdtlers

Я использую как StandardAnalyzer с полем, так что я не ожидаю, что оно будет сильно преобразовывать оригинальные слова в поле (и я проверил с этим конкретным именем и StandardAnalyzer).

Что я тут не так делаю и как это исправить?

Редактировать: Я извлекаю термины вручную с помощью каждого анализатора поля и помещаю их в отдельное строковое поле как временное решение.

1 Ответ

1 голос
/ 18 июня 2019

Если вы хотите получить условия в правильном порядке, вы также должны использовать информацию о местоположении. Протестируйте этот код:

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);
    }
}

Этот код также обрабатывает ситуацию, когда один и тот же термин (слово) используется в нескольких местах.

...