Используя комбинацию подстановочных знаков и стемминга - PullRequest
7 голосов
/ 02 февраля 2012

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

Пример:

Поиск по запросу «valv», «valve» или «valve» возвращает одинаковое количество результатов.Это имеет смысл, поскольку анализатор снежного кома сводит все до «valv».

У меня возникают проблемы при использовании подстановочного знака.Поиск по запросу «клапан *» или «клапаны *» не дает никаких результатов.Поиск «valv *» работает как положено.

Я понимаю, почему это происходит, но я не знаю, как это исправить.

Я подумал о том, чтобы написать анализатор, в котором хранятся токены со стеблем и без них.В основном применяются два анализатора и объединяются два потока токенов.Но я не уверен, что это практическое решение.

Я также думал об использовании AnalyzingQueryParser, но я не знаю, как применить это к многополюсному запросу.Кроме того, использование AnalyzingQueryParser будет возвращать результаты для «клапана» при поиске «клапаны *», а это не ожидаемое поведение.

Есть ли "предпочтительный" способ использования как подстановочных знаков, так и алгоритмов определения основ?

Ответы [ 4 ]

8 голосов
/ 02 февраля 2012

Я использовал 2 различных подхода для решения этой проблемы до

  1. Используйте два поля, одно из которых содержит термины с основами, а другое - сгенерированные, скажем, StandardAnalyzer.Когда вы анализируете поисковый запрос, если это поиск по шаблону в «стандартном» поле, если не использовать поле с основанными терминами.Это может быть сложнее в использовании, если пользователь вводит свои запросы непосредственно в QueryParser Lucene.

  2. Написать собственный анализатор и маркеры, перекрывающие индексы.Он в основном состоит из индексации исходного термина и основы в одной и той же позиции индекса, используя PositionIncrementAttribute.Вы можете заглянуть в SynonymFilter , чтобы получить пример того, как правильно использовать PositionIncrementAttribute.

Я предпочитаю решение № 2.

1 голос
/ 27 мая 2014

Это самое простое решение, и оно будет работать -

Добавьте solr.KeywordRepeatFilterFactory в свой анализатор индекса.

http://lucene.apache.org/core/4_8_0/analyzers-common/org/apache/lucene/analysis/miscellaneous/KeywordRepeatFilterFactory.html

Также добавьте RemoveDuplicatesTokenFilterFactory в конце анализатора индекса

Теперь в вашем указателе вы всегда будете иметь стеблевую и не стеблевую форму для каждого жетона в одной и той же позиции, и вы готовы идти.

1 голос
/ 02 февраля 2012

Я не думаю, что есть простой ( и правильный ) способ сделать это.

Моим решением было бы написание пользовательского анализатора запросов, который находит самую длинную строку, общую для терминов в индексе и для ваших критериев поиска.

class MyQueryParser : Lucene.Net.QueryParsers.QueryParser
{
    IndexReader _reader;
    Analyzer _analyzer;

    public MyQueryParser(string field, Analyzer analyzer,IndexReader indexReader) : base(field, analyzer)
    {
        _analyzer = analyzer;
        _reader = indexReader;
    }

    public override Query GetPrefixQuery(string field, string termStr)
    {
        for(string longestStr = termStr; longestStr.Length>2; longestStr = longestStr.Substring(0,longestStr.Length-1))
        {
            TermEnum te = _reader.Terms(new Term(field, longestStr));
            Term term = te.Term();
            te.Close();
            if (term != null && term.Field() == field && term.Text().StartsWith(longestStr))
            {
                return base.GetPrefixQuery(field, longestStr);
            }
        }

        return base.GetPrefixQuery(field, termStr);
    }
}

вы можететакже попытайтесь вызвать ваш анализатор по номеру GetPrefixQuery, который не вызывается для PrefixQuery s

TokenStream ts = _analyzer.TokenStream(field, new StringReader(termStr));
Lucene.Net.Analysis.Token token = ts.Next();
var termstring = token.TermText();
ts.Close();
return base.GetPrefixQuery(field, termstring);

Но учтите, что вы всегда можете найти случай, когда возвращаемые результаты не верны.Вот почему Lucene не учитывает анализаторы при использовании групповых символов.

0 голосов
/ 11 февраля 2012

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

...