0

我有一个存储到 Lucene 数据结构中的缓存名称列表。我想找到名字以特定字母开头的人。

例如:我的清单如下。我把它们存放在name田地里。

foo bar
blabla foo
foo2 bar
test data

当我用name:f*它搜索时返回foo bar,foo2 barblabla foo. 它会检查该字段中的每个单词并获取blabla foo。但是我需要让名字以f开头,它的第一个字母是f,而不是记录包含以开头的单词,f即使它们在句子的末尾。

任何想法 ?

4

3 回答 3

1

通配符搜索

Lucene 支持在单个词中(不是在短语查询中)的单个和多个字符通配符搜索。

要执行单个字符通配符搜索,请使用“?” 象征。

要执行多字符通配符搜索,请使用“*”符号。

单字符通配符搜索查找与替换的单字符匹配的术语。例如,要搜索“text”或“test”,您可以使用以下搜索:

te?t 多字符通配符搜索查找 0 个或更多字符。例如,要搜索 test、tests 或 tester,您可以使用搜索:

测试*

例如,使用正则表达式

RegexQuery query = new RegexQuery(newTerm("^a.*$"));


query.setRegexImplementation(new JavaUtilRegexCapabilities());

return searcher.search(query, null, 1000).totalHits;

http://lucene.apache.org/core/4_3_1/queryparser/org/apache/lucene/queryparser/classic/package-summary.html#package_description

示例代码:

        BasicConfigurator.configure();

        Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_CURRENT);

        // Store the index in memory:
        Directory directory = new RAMDirectory();
        // To store an index on disk, use this instead:
        // Directory directory = FSDirectory.open(new
        // File("./lucene/data"));
        IndexWriterConfig config = new IndexWriterConfig(
                Version.LUCENE_CURRENT, analyzer);
        IndexWriter iwriter;

        iwriter = new IndexWriter(directory, config);

        String[] words = { "Olimpia", "Cerro", "Olimpo", "Libertad",
                "Nacional", "Sol", "O'higgins", "Sao Paulo",
                "Oriente Petrolero", "Barrio Obrero", "B. Obrero" };

        for (String word : words) {
            Document doc = new Document();
            String text = word;
            doc.add(new Field("name", text, Field.Store.YES,
                    Field.Index.NOT_ANALYZED));

            // ,Field.Store.NO, Field.Index.NOT_ANALYZED
            iwriter.addDocument(doc);
        }

        iwriter.close();

        // Now search the index:

        logger.info("HelloLucene.main: query2 -----------");

        DirectoryReader ireader2 = DirectoryReader.open(directory);
        IndexSearcher isearcher2 = new IndexSearcher(ireader2);

        logger.info("HelloLucene.main: query2 -----------");
        RegexQuery query2 = new RegexQuery(new Term("name", "O.*"));
        query2.setRegexImplementation(new JavaUtilRegexCapabilities(
                JavaUtilRegexCapabilities.FLAG_CASE_INSENSITIVE));

        ScoreDoc[] hits2 = isearcher2.search(query2, null, 1000).scoreDocs;
        for (int i = 0; i < hits2.length; i++) {
            Document hitDoc = isearcher2.doc(hits2[i].doc);
            logger.info("HelloLucene.main: starting with O = "
                    + hitDoc.get("name"));

        }
于 2013-07-03T15:01:04.337 回答
1

建议使用没有标记化的字段。
此外,不要使用通配符搜索,而是使用EdgeNGramTokenFilter,它会生成令牌,并且会比通配符搜索快得多,因为它会在索引时发生。

于 2013-07-04T04:30:48.427 回答
0

默认情况下,这就是 Lucene 的运行方式。如果将字段标记为术语,并且您搜索出现在字段中任何位置的术语。对于大文本文档,这绝对有意义,因为您可能永远不想只从大量文本的开头进行搜索。

如果您希望能够作为文字字符串而不是一组标记化的术语进行搜索,那么最好的解决方案是以能够很好地支持它的方式对其进行索引。Solr.StrField是一种典型的类型选择,而不是TextField

于 2013-07-03T16:14:13.887 回答