如何在Lucene中执行通配符搜索?
我有文字:“1997_titanic”
如果我搜索“1997_titanic”,它会返回一个结果,但我无法在两次搜索中进行搜索:
1)如果我只用1997年搜索,则不会返回任何结果 2)如果有空间,例如“蜘蛛侠”,也没有找到任何结果。
我从数据库中检索所有电影信息并将其存储在Lucene Documents中:
public Document createMovieDoc(Movie m){
document.add(new StoredField("moviename", m.getName()));
TextField field = new TextField("movienameSearch", m.getName().toLowerCase(), Store.NO);
field.setBoost(5.0f);
document.add(field);
}
要搜索,我有这个方法:
public List searh(String txt){
PhraseQuery phQuery= new PhraseQuery();
Term term = new Term("movienameSearch", txt.toLowerCase());
BooleanQuery b = new BooleanQuery();
b.add(phQuery, Occur.SHOULD);
TopFieldDocs tp= searcher.search(b, 20, ..);
for(int i=0;i<tp.length;i++)
{
int mId = tp[i].doc;
Document d = searcher.doc(mId);
String moviename = d.get("moviename");
list.add(moviename);
}
return list;
}
答案 0 :(得分:0)
我不确定您使用哪种分析仪进行索引。听起来像是WhitespaceAnalyzer
?听起来,当索引“1997_titanic”仍然是单个令牌时,“蜘蛛侠”被分成令牌“蜘蛛”和“男人”。
也可以SimpleAnalyzer
使用LetterTokenizer
。这将使得无法搜索“1997”,因为该标记化器将消除文本的索引表示的所有数字。
您的搜索方法看起来不正确。您没有向PhraseQuery
添加任何字词,因此我不希望它能找到任何内容。您必须add一些条款才能找到任何内容。您在所提供的内容中创建了Term
,但该术语并未执行任何操作。也许这与你如何选择你的摘录或某事有关?不确定,我有点困惑。
为了手动构建PhraseQuery,您必须单独添加每个术语,因此要搜索“蜘蛛侠”,您可以执行以下操作:
PhraseQuery phQuery= new PhraseQuery();
phQuery.add(new Term("movienameSearch", "spider"));
phQuery.add(new Term("movienameSearch", "man"));
这需要您了解分析仪在索引时执行的操作,并自行标记输入以适应。更简单的解决方案是使用QueryParser
:
//With whatever analyzer you like to use.
QueryParser parser = new QueryParser(Version.LUCENE_46, "defaultField", analyzer);
Query query = parser.parse("movienameSearch:\"" + txt.toLowerCase() + "\"");
TopFieldDocs tp= searcher.search(query, 20);
这允许您依靠相同的分析器进行索引和查询,因此您不必知道如何将您的短语标记为适合。
就单独找到“1997”和“泰坦尼克号”而言,我建议只使用StandardAnalyzer
。它会将它们标记为离散标记,使用简单的查询(例如movienameSearch:1997
)可以非常轻松地搜索它们。