Rik*_*son 7 java lucene search
我正在尝试使用Apache Lucene创建一个可搜索的电话/本地商业目录.
我有街道名称,公司名称,电话号码等字段.我遇到的问题是,当我尝试在街道上搜索街道名称有多个单词(例如"新月")时,不会返回任何结果.但是,如果我尝试用一个单词搜索,例如'新月',我会得到我想要的所有结果.
我正在使用以下内容索引数据:
String LocationOfDirectory = "C:\\dir\\index";
StandardAnalyzer analyzer = new StandardAnalyzer(Version.LUCENE_34);
Directory Index = new SimpleFSDirectory(LocationOfDirectory);
IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE.34, analyzer);
IndexWriter w = new IndexWriter(index, config);
Document doc = new Document();
doc.add(new Field("Street", "the crescent", Field.Store.YES, Field.Index.Analyzed);
w.add(doc);
w.close();
Run Code Online (Sandbox Code Playgroud)
我的搜索工作如下:
int numberOfHits = 200;
String LocationOfDirectory = "C:\\dir\\index";
TopScoreDocCollector collector = TopScoreDocCollector.create(numberOfHits, true);
Directory directory = new SimpleFSDirectory(new File(LocationOfDirectory));
IndexSearcher searcher = new IndexSearcher(IndexReader.open(directory);
WildcardQuery q = new WildcardQuery(new Term("Street", "the crescent");
searcher.search(q, collector);
ScoreDoc[] hits = collector.topDocs().scoreDocs;
Run Code Online (Sandbox Code Playgroud)
我已经尝试交换通配符查询的短语查询,首先使用整个字符串,然后将字符串拆分为空格并将它们包装在如下的BooleanQuery中:
String term = "the crescent";
BooleanQuery b = new BooleanQuery();
PhraseQuery p = new PhraseQuery();
String[] tokens = term.split(" ");
for(int i = 0 ; i < tokens.length ; ++i)
{
p.add(new Term("Street", tokens[i]));
}
b.add(p, BooleanClause.Occur.MUST);
Run Code Online (Sandbox Code Playgroud)
但是,这不起作用.我尝试使用KeywordAnalyzer而不是StandardAnalyzer,但随后所有其他类型的搜索也停止了.我已经尝试用其他字符(+和@)替换空格,并将查询转换为此表单,但仍然无效.我认为它不起作用,因为+和@是没有索引的特殊字符,但我似乎找不到任何字符都是这样的列表.
我开始有点生气,有谁知道我做错了什么?
谢谢,Rik
Art*_*wak 13
你没有得到你的文件的原因是你正在使用的索引StandardAnalyzer
,它将标记转换为小写并删除停用词.因此,为您的示例编制索引的唯一术语是"新月".但是,不会分析通配符查询,因此"the"包含在查询的必需部分中.您的方案中的短语查询也是如此.
KeywordAnalyzer
可能不太适合您的用例,因为它将整个字段内容作为单个标记.您可以使用SimpleAnalyzer
街道字段 - 它将在所有非字母字符上拆分输入,然后将它们转换为小写字母.您也可以考虑使用WhitespaceAnalyzer
与LowerCaseFilter
.您需要尝试不同的选项,找出最适合您的数据和用户的选项.
此外,PerFieldAnalyzerWrapper
如果更改该字段的分析器会破坏其他搜索,则可以为每个字段使用不同的分析器(例如,使用).
我发现我不使用QueryParser生成查询的尝试不起作用,所以我不再尝试创建自己的查询并使用QueryParser.我在网上看到的所有建议都表明你应该在索引期间使用的QueryParser中使用相同的Analyzer,所以我使用了StandardAnalyzer来构建QueryParser.
这适用于此示例,因为StandardAnalyzer在索引期间从街道"the crescent"中删除单词"the",因此我们无法搜索它,因为它不在索引中.
但是,如果我们选择搜索"Grove Road",我们就会遇到开箱即用功能的问题,即查询将返回包含"Grove"或"Road"的所有结果.通过设置QueryParser可以很容易地解决这个问题,因此它的默认操作是AND而不是OR.
最后,正确的解决方案如下:
int numberOfHits = 200;
String LocationOfDirectory = "C:\\dir\\index";
TopScoreDocCollector collector = TopScoreDocCollector.create(numberOfHits, true);
Directory directory = new SimpleFSDirectory(new File(LocationOfDirectory));
IndexSearcher searcher = new IndexSearcher(IndexReader.open(directory);
StandardAnalyzer analyzer = new StandardAnalyzer(Version.LUCENE_35);
//WildcardQuery q = new WildcardQuery(new Term("Street", "the crescent");
QueryParser qp = new QueryParser(Version.LUCENE_35, "Street", analyzer);
qp.setDefaultOperator(QueryParser.Operator.AND);
Query q = qp.parse("grove road");
searcher.search(q, collector);
ScoreDoc[] hits = collector.topDocs().scoreDocs;
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
22950 次 |
最近记录: |