试图获得更多与 lucene 的匹配

Posted

技术标签:

【中文标题】试图获得更多与 lucene 的匹配【英文标题】:Trying to get more matches with lucene 【发布时间】:2017-12-16 15:45:41 【问题描述】:

我正在使用 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;

这在没有不一致的情况下非常有效,即使对于非英文字符也是如此。但它不会返回一个匹配项,例如,如果我收到一首标题为“The Sun Was In My Eyes: Part One”的歌曲,但我对应的文件的标题为“The Sun Was In My Eyes: Part 1” ”,或者如果我像“Pt. 1”一样收到它。

当标题的单词多于相应的文件时,我也找不到匹配项,例如“所有时代的终结(烈士之火)”与“所有时代的终结”相对。专辑名称也可能发生。

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

【问题讨论】:

【参考方案1】:

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

【讨论】:

以上是关于试图获得更多与 lucene 的匹配的主要内容,如果未能解决你的问题,请参考以下文章

使用Lucene Query测试文档是否匹配

lucene 怎么这么快计算文档的交集?

Lucene搜索流程(上)

倒排索引,正排索引与lucene

lucene prefixQuery

全文检索——Lucene