我使用Lucene.Net实现了一个搜索工具。该指数包括英国学术资格,包括“A Level”。
我希望用户能够使用短语“A Level”进行搜索,但是使用标准分析器时,“A”被删除为停用词,因此只有“Level”被索引/搜索。
解决这个问题的最佳选择是什么?我猜我需要通过创建自定义分析器以某种方式将“A Level”标记为“A-Level”或类似物。
这是最好的方法吗?
编辑:
请注意,我不希望整个搜索成为短语查询。即在我的搜索框中,我希望用户能够输入<“A Level”和英语数学物理>这将返回任何“A Level”和英语数学或物理。更新问题以反映这一点。
我特别喜欢在'A Level'的所有情况下继续使用'A'作为停用词
短语“A Level”不在其自己的特定字段中,它位于可能包含该短语的自由文本字段中。
答案 0 :(得分:3)
使用PhraseQuery - 可以通过布尔结构与任何其他结合使用
<强> EDITED 强>
您无需搜索整个词组。对于你的样本它看起来像跟随(抱歉它是伪代码,因为我现在无法测试)
BooleanQuery rootQuery = new ...
PhraseQuery q1 = new PhraseQuery("A Level");
TermQuery q2 = new TermQuery("English");
TermQuery q3 = new TermQuery("Maths");
TermQuery q4 = new TermQuery("Physics");
rootQuery.Add(q1, BooleanClause.Occur.SHOULD); //or MUST - depends on you
rootQuery.Add(q2, BooleanClause.Occur.SHOULD);
rootQuery.Add(q3, BooleanClause.Occur.SHOULD);
rootQuery.Add(q4, BooleanClause.Occur.SHOULD);
答案 1 :(得分:2)
我认为Lucene目前无法做到这一点。我有一个半完成的插件,你可以看到它here。它没有设置位置和偏移属性,这意味着短语搜索将无法正常工作,但希望它能为您提供一个良好的开端。
答案 2 :(得分:1)
您是如何索引内容的 - 您使用的是哪种分析仪?如果您使用的是StandardAnalyzer,则可以在构造函数中指定停用词(可以使用空列表):
Analyzer analyzer = new StandardAnalyzer(Lucene.Net.Util.Version.LUCENE_29, new Hashtable());
所以使用上层分析器索引contenxt。之后,您可以使用QueryParser查询内容(请务必使用上面的分析器),或者您可以手动构建查询:
// Phrase query
PhraseQuery phraseQuery = new PhraseQuery();
phraseQuery.Add(new Term("MyField", "A"));
phraseQuery.Add(new Term("MyField", "Level"));
// Or query
BooleanQuery orQuery = new BooleanQuery();
orQuery.Add(new BooleanClause(new TermQuery(new Term("MyField", "English")), BooleanClause.Occur.SHOULD));
orQuery.Add(new BooleanClause(new TermQuery(new Term("MyField", "Maths")), BooleanClause.Occur.SHOULD));
orQuery.Add(new BooleanClause(new TermQuery(new Term("MyField", "Physics")), BooleanClause.Occur.SHOULD));
// Main query
BooleanQuery query = new BooleanQuery();
query.Add(phraseQuery, BooleanClause.Occur.MUST);
query.Add(orQuery, BooleanClause.Occur.MUST);
再见
答案 3 :(得分:1)
与StandardAnalyzer不同,KeywordAnalyzer不会对字符串进行标记。我假设有一个.net实现 - possibly this?。
我经常做这样的事情(小心,Java遵循):
private ReusableAnalyzer getReusableAnalyzer(String fieldName, Reader reader) {
boolean phrase = treatAsPhrase(fieldName);
ReusableAnalyzer ra = new ReusableAnalyzer();
TokenStream result = phrase ? new KeywordTokenizer(reader) : new StandardTokenizer(version, reader);
我使用字段名称来确定是否将文本视为“短语”。
答案 4 :(得分:1)
这在Lucene中可以通过更多的自定义来实现。
1)创建一个单独的字段,其中保留停用词。您需要创建自己的分析器,该分析器继承自StandardAnalyzer,但在基础构造函数中没有指定停用词。
public class PreserveStopWordsAnalyzer : StandardAnalyzer
{
public PreserveStopWordsAnalyzer() : base(Version.LUCENE_29, new Hashtable())
{}
}
2)针对“停用词”字段搜索引用的字词。例如:
+RegularField:English +StopWordField:"A Level"