我有一个缓存的名称列表,我存储到Lucene数据结构中。我希望得到名字以特定字母开头的人。
例如:
我的清单如下。我将它们存储到name
字段中。
foo bar
blabla foo
foo2 bar
test data
当我使用name:f*
进行搜索时,会返回foo bar
,foo2 bar
和blabla foo
。它会检查字段中的每个单词并获得blabla foo
。但是我需要以f
开头,其首字母是f
,而不是记录包含以f
开头的单词,即使它们位于句子的末尾。
有什么想法吗?
答案 0 :(得分:1)
通配符搜索
Lucene支持单个术语内的单个和多个字符通配符搜索(不在短语查询中)。
要执行单字符通配符搜索,请使用“?”符号
要执行多字符通配符搜索,请使用“*”符号。
单字符通配符搜索会查找与替换的单个字符匹配的字词。例如,要搜索“文本”或“测试”,您可以使用搜索:
TE?吨 多字符通配符搜索查找0个或更多字符。例如,要搜索测试,测试或测试人员,您可以使用搜索:
试验*
示例,使用正则表达式
RegexQuery query = new RegexQuery(newTerm("^a.*$"));
query.setRegexImplementation(new JavaUtilRegexCapabilities());
return searcher.search(query, null, 1000).totalHits;
示例代码:
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"));
}
答案 1 :(得分:1)
建议在没有标记化的情况下使用该字段 此外,不使用通配符搜索,而是使用会生成令牌的EdgeNGramTokenFilter,并且比通配符搜索要快得多,因为它会在索引时发生。
答案 2 :(得分:0)
默认情况下,Lucene就是这样做的。如果将字段标记为术语,则搜索字段中任何位置的术语。对于大型文本文档,这是绝对有意义的,因为您可能永远不会只想从大量文本的开头进行搜索。
如果您希望能够搜索文字字符串而不是标记化的术语集,那么最佳解决方案是以支持该字符串的方式对其进行索引。 Solr.StrField是典型的类型选择,而不是TextField。