2017-12-16 5 views
1

Ich benutze Java und Lucene, um jedes Lied einer Liste, die ich von einem Dienst mit lokalen Dateien erhalte, zu vergleichen. Womit ich gerade zu kämpfen habe, ist eine Suchanfrage, die mir die größtmögliche Anzahl an Übereinstimmungen pro Song ermöglicht. Wenn ich pro Song mindestens eine passende Datei bekommen könnte, wäre das großartig. DieseVersuche, mehr Übereinstimmungen mit Lucene zu erhalten

ist, was ich habe 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; 
} 

Das funktioniert sehr gut, wenn es keine Widersprüche sind, auch für nicht-englische Zeichen. Aber es bringt mir kein einziges Spiel zurück, wenn ich zum Beispiel ein Lied mit dem Titel "Die Sonne war in meinen Augen: Teil eins" bekomme, aber meine entsprechende Datei trägt den Titel "Die Sonne war in meinen Augen: Teil 1 "oder wenn ich es wie" Pt. 1 "empfange.

Ich bekomme auch keine Treffer, wenn die Titel mehr Wörter haben als die entsprechenden Dateien, wie "Das Ende aller Zeiten (Märtyrerfeuer)" gegen "Das Ende aller Zeiten". Könnte auch für Albennamen passieren.

Also, was ich gerne wissen würde, ist, welche Verbesserungen ich in meinem Code machen sollte, um mehr Übereinstimmungen zu bekommen.

Antwort

0

So fand ich schließlich heraus, dass die Verwendung einer PhraseQuery für den Titel oder das Album nicht der beste Ansatz ist, da dies Lucene dazu veranlassen würde, nach einem genauen Ausdruck einer solchen Phrase zu suchen.

Was ich getan habe, war eine TermQuery für jedes der Wörter, sowohl für den Titel und das Album, und alles in einer BooleanQuery zu verbinden.

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