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,使用该变通方法似乎并不干净。
感谢的任何帮助
我想在自己的自动完成实现中使用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;
这似乎奏效了。我仍在努力确定minGram
和maxGram
的最佳值,以及处理长度小于minGram
的项的最佳方法,但这是一个良好的开端。