【问题标题】:Scrub Lucene search terms with the Standard Analyzer使用标准分析器清理 Lucene 搜索词
【发布时间】:2013-01-22 17:35:00
【问题描述】:

我们正在从搜索词字符串中构建一个布尔查询来搜索我们的 Lucene 索引。我希望使用标准分析器来分析这些字符串,标准分析器是我们用于索引的分析器。例如,foo-bar 1-2-3 应该分解为foobar1-2-3,因为 Lucene 文档指出连字符会导致数字保持在一起,但单词会被标记化。最好的方法是什么?

目前我正在通过 QueryParser 运行我的搜索词字符串。

QueryParser parser = new QueryParser("", new StandardAnalyzer()); 
Query query = parser.parse(aSearchTermString);

这样做的问题是插入了引号。例如,foo-bar 1-2-3 变为 "foo bar"1-2-3,它不会返回任何内容,因为 Lucene 会将 foo-bar 标记为 foobar

我绝对不想通过删除带有replace 的引号来解决这种情况,因为我觉得我可能遗漏了什么或做错了什么。

【问题讨论】:

    标签: java lucene compass-lucene


    【解决方案1】:

    我实际上得到了 StandardAnalyzer 的不同结果。考虑这段代码(使用 Lucene v4):

    public class Tokens {
    
        private static void printTokens(String string, Analyzer analyzer) throws IOException {
            System.out.println("Using " + analyzer.getClass().getName());
            TokenStream ts = analyzer.tokenStream("default", new StringReader(string));
            OffsetAttribute offsetAttribute = ts.addAttribute(OffsetAttribute.class);
            CharTermAttribute charTermAttribute = ts.addAttribute(CharTermAttribute.class);
    
            while(ts.incrementToken()) {
                int startOffset = offsetAttribute.startOffset();
                int endOffset = offsetAttribute.endOffset();
                String term = charTermAttribute.toString();
                System.out.println(term + " (" + startOffset + " " + endOffset + ")");
            }
            System.out.println();
        }
    
        public static void main(String[] args) throws IOException {
            printTokens("foo-bar 1-2-3", new StandardAnalyzer(Version.LUCENE_40));
            printTokens("foo-bar 1-2-3", new ClassicAnalyzer(Version.LUCENE_40));
    
            QueryParser standardQP = new QueryParser(Version.LUCENE_40, "", new StandardAnalyzer(Version.LUCENE_40));
            BooleanQuery q1 = (BooleanQuery) standardQP.parse("someField:(foo\\-bar\\ 1\\-2\\-3)");
            System.out.println(q1.toString() + "     # of clauses:" + q1.getClauses().length);
        }
    }
    

    上图:

    Using org.apache.lucene.analysis.standard.StandardAnalyzer
    foo (0 3)
    bar (4 7)
    1 (8 9)
    2 (10 11)
    3 (12 13)
    
    Using org.apache.lucene.analysis.standard.ClassicAnalyzer
    foo (0 3)
    bar (4 7)
    1-2-3 (8 13)
    
    someField:foo someField:bar someField:1 someField:2 someField:3     # of clauses:5
    

    所以上面的代码证明StandardAnalyzerClassicAnalyzer 不同,应该将1-2-3 拆分为不同的标记——完全按照你的意愿。对于查询,你需要对每个关键字进行转义,包括空格,否则 QP 认为这有不同的含义。

    如果您不想转义查询字符串,您始终可以手动对其进行标记(如上面的printTokens 方法),然后用TermQuery 包装每个标记并将所有术语查询堆叠到BooleanQuery 中。

    【讨论】:

    • 如果 Apache 文档声明 StandardAnalyzer 不会在连字符上拆分数字,为什么 StandardAnalyzer 会标记 1-2-3
    • 你能指出这个关于 StandardAnalyzer 的声明吗?我发现StandardAnalyzer 使用StandardTokenizer,它使用Unicode Standard Annex #29。 FWIW,我没有对后者进行过深入的研究。
    • 当然,here it is
    • Ghm,如果我在 ClassicAnalyzer 中使用连字符 (‐),我会将数字文本拆分为标记,但如果我使用减号 (-),它不会拆分……这更令人困惑!很可能是 Javadoc 已经过时了。想深入了解 Unicode 标准附件 #29?
    猜你喜欢
    • 2011-08-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多