代码之家  ›  专栏  ›  技术社区  ›  Tharkius

试图与lucene进行更多匹配

  •  1
  • Tharkius  · 技术社区  · 7 年前

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

    当没有不一致时,即使对于非英语字符,这也很有效。但它不会返回任何匹配项,例如,如果我收到一首标题为“太阳在我眼中:第一部分”的歌曲,但我相应的文件标题为“太阳在我眼中:第1部分”,或者如果我收到类似“第1部分”的歌曲。

    我也没有找到匹配项,因为标题的字数比相应的文件多,比如“所有时代的终结(烈士之火)”与“所有时代的终结”相对应。专辑名称也可能出现这种情况。

    所以,我想知道的是,为了获得更多匹配,我应该在代码中做些什么改进。

    1 回复  |  直到 7 年前
        1
  •  0
  •   Tharkius    7 年前

    因此,我最终发现,对标题或专辑使用短语查询并不是最好的方法,因为这会导致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;
    }