Lucene.Net NGramAnalyzer生成带有引号的ngrams的查询,例如[titleNGram:"

本文关键字:例如 查询 titleNGram quot ngrams Lucene NGramAnalyzer Net | 更新日期: 2023-09-27 18:04:25

跟随

https://github.com/Sitecore/autohaus/blob/master/Autohaus.Custom/Indexing/Analyzers/NGramAnalyzer.cs

我创建了这个自定义分析器

public class NGramAnalyzer : Analyzer
{
    private readonly Version _version;
    private readonly int _minGram;
    private readonly int _maxGram;
    public NGramAnalyzer(Version version, int minGram = 2, int maxGram = 8)
    {
        _version = version;
        _minGram = minGram;
        _maxGram = maxGram;
    }
    public override TokenStream TokenStream(string fieldName, TextReader reader)
    {
        // Splits words at punctuation characters, removing punctuation.
        // Splits words at hyphens, unless there's a number in the token...
        // Recognizes email addresses and internet hostnames as one token.
        var tokenizer = new StandardTokenizer(_version, reader);
        TokenStream filter = new StandardFilter(tokenizer);
        // Normalizes token text to lower case.
        filter = new LowerCaseFilter(filter);
        // Removes stop words from a token stream.
        filter = new StopFilter(true, filter, StopAnalyzer.ENGLISH_STOP_WORDS_SET);
        return new NGramTokenFilter(filter, _minGram, _maxGram);
    }
}

我遇到的问题是它生成了形式的查询

[ titleNGram:"his ist sto tor ory" ] instead of [ titleNGram:his ist sto tor ory]

为了[历史]。注意第一个上的引号

我该如何使它不引用查询。

我在这里找到了类似的Java Lucene讨论

https://forum.hibernate.org/viewtopic.php?f=9&t=999916&view=下一个

有没有一种方法可以在不产生变通方法的情况下解决这个问题。

我使用的是PerFieldAnalyzerWrapper,使用该变通方法似乎并不干净。

感谢的任何帮助

Lucene.Net NGramAnalyzer生成带有引号的ngrams的查询,例如[titleNGram:"

我想在自己的自动完成实现中使用NGramAnalyzer,这是我唯一能找到的生成所需内容的尝试,所以这就是我的起点。

我遇到了与你描述的相同的问题,并提出了一个相当干净的解决方案。

原因似乎在QueryParser.cs:494的Query GetFieldQuery(String field, String queryText)中。这最终被称为QueryParser.Parse的一部分。如果有多个令牌要添加到查询中("his"、"ist"等是多个令牌(,并且称为severalTokensAtSamePosition的布尔值为false,则GetFieldQuery构造一个短语查询(在第677行(,并在返回之前将所有令牌添加到该查询中(第705行(。

我们想要的是将所有令牌添加到一个布尔查询中,并使用Occur.SHOULD。我尝试对QueryParser进行子类化并覆盖GetFieldQuery,因为它被标记为virtual。然而,我需要复制其余的功能,并发现有相当多的private变量引用。相反,我发现了如何从解析的查询中提取令牌,并在运行搜索之前将它们插入到BooleanQuery中:

var query = new BooleanQuery();
foreach( var word in terms ) {
    var parsed = parser.Parse( word );
    var extractedTerms = new HashSet<Term>();
    parsed.ExtractTerms( extractedTerms );
    foreach( var term in extractedTerms ) {
        query.Add( new TermQuery( term ), Occur.SHOULD );
    }
}
var resultDocs = searcher.Search( query, maxResults ).ScoreDocs;

这似乎奏效了。我仍在努力确定minGrammaxGram的最佳值,以及处理长度小于minGram的项的最佳方法,但这是一个良好的开端。