我正在使用Java和lucene来匹配我从服务接收的列表中的每首歌曲以及本地文件。我目前正在努力解决的问题是找到一个可以让每首歌曲获得最多匹配的查询。如果我能为每首歌曲获得至少一个匹配的文件,那就太棒了。
这就是我的主题:
public List<String> getMatchesForSong(String artist, String title, String album) throws ParseException, IOException {
StandardAnalyzer analyzer = new StandardAnalyzer();
String defaultQuery = "(title: \"%s\"~2) AND ((artist: \"%s\") OR (album: \"%s\"))";
String searchQuery = String.format(defaultQuery, title, artist, album);
Query query = new QueryParser("title", analyzer).parse(searchQuery);
if (indexWriter == null) {
indexWriter = createIndexWriter(indexDir);
indexSearcher = createIndexSearcher(indexWriter);
}
TopDocs topDocs = indexSearcher.search(query, 20);
if (topDocs.totalHits > 0) {
return parseScoreDocsList(topDocs.scoreDocs);
}
return null;
}
当没有不一致时,即使对于非英语字符,这也很有效。但是,如果我收到一首标题为“太阳在我眼中:第一部分”的歌曲,它就不会给我一场比赛,但我的相应文件标题为“太阳在我眼中:第一部分” “,或者如果我像”Pt.1“那样收到它。
当标题比相应的文件有更多的单词时,我也没有得到匹配,例如“所有时代的结束(烈士之火)”反对“所有时代的结束”。专辑名称也可能发生。
所以,我想知道的是我应该在代码中做些什么改进,以获得更多匹配。
答案 0 :(得分:0)
所以我最终发现使用PhraseQuery作为标题或专辑,并不是最好的方法,因为这会导致lucene搜索这样一个短语的确切内容。
我最终做的是为标题和专辑中的每个单词制作一个TermQuery,并将所有内容加入到BooleanQuery中。
private Query parseQueryForSong(String artist, String title, String album) throws ParseException {
String[] artistArr = artist.split(" ");
String[] titleArr = sanitizePhrase(title).split(" ");
String[] albumArr = sanitizePhrase(album).split(" ");
BooleanQuery.Builder mainQueryBuilder = new BooleanQuery.Builder();
BooleanQuery.Builder albumQueryBuilder = new BooleanQuery.Builder();
PhraseQuery artistQuery = new PhraseQuery("artist", artistArr);
for (String titleWord : titleArr) {
if (!titleWord.isEmpty()) {
mainQueryBuilder.add(new TermQuery(new Term("title", titleWord)), BooleanClause.Occur.SHOULD);
}
}
for (String albumWord : albumArr) {
if (!albumWord.isEmpty()) {
albumQueryBuilder.add(new TermQuery(new Term("album", albumWord)), BooleanClause.Occur.SHOULD);
}
}
mainQueryBuilder.add(artistQuery, BooleanClause.Occur.MUST);
mainQueryBuilder.add(albumQueryBuilder.build(), BooleanClause.Occur.MUST);
StandardAnalyzer analyzer = new StandardAnalyzer();
Query mainQuery = new QueryParser("title", analyzer).parse(mainQueryBuilder.build().toString());
return mainQuery;
}