尝试与lucene进行更多匹配

Trying to get more matches with lucene

我正在使用 Java 和 lucene 来匹配我从服务收到的列表中的每首歌曲和本地文件。我目前正在苦苦挣扎的是找到一个查询,该查询将使我获得每首歌曲尽可能多的匹配项。如果每首歌至少能得到一个匹配的文件,那就太好了。

这是我的 atm:

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;
}

如果没有不一致,即使是 non-English 个字符,这种方法也能很好地工作。但它不会 return 我一个单一的匹配,例如,如果我收到一首标题为 "The Sun Was In My Eyes: Part One" 的歌曲,但我相应的文件有标题 "The Sun Was In My Eyes: Part 1",或者如果我收到它"Pt. 1".

我也没有找到匹配项,当标题的字数比相应的文件多时,例如 "The End of all Times (Martyrs Fire)" 与 "The End of all Times" 相对。专辑名称也可能发生。

所以,我想知道我应该对我的代码进行哪些改进,以获得更多的匹配。

所以我最终发现对标题或专辑使用 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;
}