Lucene.Net - 如何将空格分隔的短语视为单个标记?

时间:2011-01-14 10:16:53

标签: c# .net lucene lucene.net

我使用Lucene.Net实现了一个搜索工具。该指数包括英国学术资格,包括“A Level”。

我希望用户能够使用短语“A Level”进行搜索,但是使用标准分析器时,“A”被删除为停用词,因此只有“Level”被索引/搜索。

解决这个问题的最佳选择是什么?我猜我需要通过创建自定义分析器以某种方式将“A Level”标记为“A-Level”或类似物。

这是最好的方法吗?

编辑:

请注意,我不希望整个搜索成为短语查询。即在我的搜索框中,我希望用户能够输入<“A Level”和英语数学物理>这将返回任何“A Level”和英语数学或物理。更新问题以反映这一点。

我特别喜欢在'A Level'的所有情况下继续使用'A'作为停用词

短语“A Level”不在其自己的特定字段中,它位于可能包含该短语的自由文本字段中。

5 个答案:

答案 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"