Как удалить множественное число в Lucene.NET?

Я пытаюсь извлечь некоторые ключевые слова из текста. Это работает отлично, но мне нужно удалить множественное число.

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

Во-первых, я индексирую документ в индексе RAMDirectory,

RAMDirectory idx = new RAMDirectory();
using (IndexWriter writer = 
    new IndexWriter(
        idx,
        new CustomStandardAnalyzer(StopWords.Get(this.Language),
        Lucene.Net.Util.Version.LUCENE_30, this.Language),
        IndexWriter.MaxFieldLength.LIMITED))
{
    writer.AddDocument(createDocument(this._text));
    writer.Optimize();
}

Затем я извлекаю ключевые слова:

var list = new List<KeyValuePair<int, string>>();
using (var reader = IndexReader.Open(directory, true))
{
    var tv = reader.GetTermFreqVector(0, "text");
    if (tv != null)
    {
        string[] terms = tv.GetTerms();
        int[] freq = tv.GetTermFrequencies();

        for (int i = 0; i < terms.Length; i++)
            list.Add(new KeyValuePair<int, string>(freq[i], terms[i]));
    }
}

в списке терминов могут быть такие термины, как "президент" и "президенты"
Как я могу удалить это?
Мой CustomStandardAnalyzer использует это:

public override TokenStream TokenStream(string fieldName, System.IO.TextReader reader)
{
    //create the tokenizer
    TokenStream result = new StandardTokenizer(this.version, reader);

    //add in filters
    result = new Lucene.Net.Analysis.Snowball.SnowballFilter(result, this.getStemmer()); 
    result = new LowerCaseFilter(result);
    result = new ASCIIFoldingFilter(result);
    result = new StopFilter(true, result, this.stopWords ?? StopWords.English);

    return result;
}

Поэтому я уже использую SnowballFilter (с правильным стеммером для конкретного языка). Как удалить множественное число?


person Fabske    schedule 30.06.2013    source источник
comment
Это должно быть что-то в частях кода, которые вы не показываете, то, что вы показываете нам, должно работать, если вы используете Porter Stemmer. Я добавлю некоторый код, который в основном ваш, с некоторыми вещами, которые я жестко запрограммировал (стеммер), и это работает.   -  person Jf Beaulac    schedule 15.07.2013


Ответы (1)


Мой вывод из следующей программы:

text:and
text:presid
text:some
text:text
text:with
class Program
{
    private class CustomStandardAnalyzer : Analyzer
    {
        public override TokenStream TokenStream(string fieldName, System.IO.TextReader reader)
        {
            //create the tokenizer
            TokenStream result = new StandardTokenizer(Lucene.Net.Util.Version.LUCENE_30, reader);
            //add in filters
            result = new Lucene.Net.Analysis.Snowball.SnowballFilter(result, new EnglishStemmer()); 
            result = new LowerCaseFilter(result);
            result = new ASCIIFoldingFilter(result);
            result = new StopFilter(true, result, new HashSet<string>());
            return result;
        }
    }

    private static Document createDocument(string text)
    {
        Document d = new Document();
        Field f = new Field("text", "", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS);
        f.SetValue(text);
        d.Add(f);
        return d;
    }

    static void Main(string[] args)
    {

        RAMDirectory idx = new RAMDirectory();
        using (IndexWriter writer =
            new IndexWriter(
                idx,
                new CustomStandardAnalyzer(),
                IndexWriter.MaxFieldLength.LIMITED))
        {
            writer.AddDocument(createDocument("some text with president and presidents"));
            writer.Commit();
        }

        using (var reader = IndexReader.Open(idx, true))
        {
            var terms = reader.Terms(new Term("text", ""));
            if (terms.Term != null)
                do
                    Console.WriteLine(terms.Term);
                while (terms.Next());
        }
        Console.ReadLine();

    }
}
person Jf Beaulac    schedule 15.07.2013
comment
Спасибо за помощь. Проблема в том, что я хочу получить ключевые слова, а presid — это не ключевое слово, оно должно возвращать President. Я пытался использовать SnowballFilter, но он содержит слово, которое отличается от простого удаления множественного числа. Ключевое слово должно быть существующим словом, потому что оно будет видно пользователю. - person Fabske; 17.07.2013
comment
Ах хорошо, теперь я понимаю. Я не знаю, было ли что-то подобное уже сделано в .NET, но Solr (java) имеет solr.EnglishMinimalStemFilterFactory, который является стеммером, который обрабатывает только формы множественного числа. - person Jf Beaulac; 17.07.2013
comment
Я посмотрю исходный код этого класса и проверю, смогу ли я преобразовать его в С#. Я также нашел еще один код для удаления множественного числа в С#. Но оба только для английского, и мой пакет должен поддерживать как минимум 3 языка (en, fr, nl). - person Fabske; 18.07.2013