Semantic indexing for composer/lyricist

This commit is contained in:
Antoine Gersant 2024-08-09 13:02:49 -07:00
parent 0841c15f48
commit a2232aa9f2
3 changed files with 75 additions and 23 deletions
src
app/index
server/dto

View file

@ -4,7 +4,7 @@ use std::{
path::PathBuf,
};
use lasso2::{RodeoReader, Rodeo};
use lasso2::{Rodeo, RodeoReader};
use rand::{rngs::ThreadRng, seq::IteratorRandom};
use serde::{Deserialize, Serialize};
@ -17,7 +17,9 @@ use super::storage::fetch_song;
pub struct Artist {
pub name: Option<String>,
pub albums: Vec<Album>,
pub album_appearances: Vec<Album>,
pub song_credits: Vec<Album>, // Albums where this artist shows up as `artist` without being `album_artist`
pub composer_credits: Vec<Album>, // Albums where this artist shows up as `composer` without being `artist` or `album_artist`
pub lyricist_credits: Vec<Album>, // Albums where this artist shows up as `lyricist` without being `artist` or `album_artist`
}
#[derive(Debug, Default, PartialEq, Eq)]
@ -72,24 +74,48 @@ impl Collection {
albums
};
let album_appearances = {
let mut album_appearances = a
.album_appearances
let sort_albums = |a: &Album, b: &Album| {
(&a.artists, a.year, &a.name)
.partial_cmp(&(&b.artists, b.year, &b.name))
.unwrap()
};
let song_credits = {
let mut albums = a
.song_credits
.iter()
.filter_map(|key| self.get_album(strings, key.clone()))
.collect::<Vec<_>>();
album_appearances.sort_by(|a, b| {
(&a.artists, a.year, &a.name)
.partial_cmp(&(&b.artists, b.year, &b.name))
.unwrap()
});
album_appearances
albums.sort_by(&sort_albums);
albums
};
let composer_credits = {
let mut albums = a
.composer_credits
.iter()
.filter_map(|key| self.get_album(strings, key.clone()))
.collect::<Vec<_>>();
albums.sort_by(&sort_albums);
albums
};
let lyricist_credits = {
let mut albums = a
.lyricist_credits
.iter()
.filter_map(|key| self.get_album(strings, key.clone()))
.collect::<Vec<_>>();
albums.sort_by(&sort_albums);
albums
};
Artist {
name: a.name.map(|s| strings.resolve(&s).to_string()),
albums,
album_appearances,
song_credits,
composer_credits,
lyricist_credits,
}
})
}
@ -196,17 +222,35 @@ impl Builder {
fn add_album_to_artists(&mut self, song: &storage::Song) {
let album_key: AlbumKey = song.album_key();
for artist_name in &song.album_artists {
let artist = self.get_or_create_artist(*artist_name);
for name in &song.album_artists {
let artist = self.get_or_create_artist(*name);
artist.albums.insert(album_key.clone());
}
for artist_name in &song.artists {
let artist = self.get_or_create_artist(*artist_name);
for name in &song.artists {
let artist = self.get_or_create_artist(*name);
if song.album_artists.is_empty() {
artist.albums.insert(album_key.clone());
} else if !song.album_artists.contains(artist_name) {
artist.album_appearances.insert(album_key.clone());
} else if !song.album_artists.contains(name) {
artist.song_credits.insert(album_key.clone());
}
}
for name in &song.composers {
let is_also_artist = song.artists.contains(name);
let is_also_album_artist = song.artists.contains(name);
if !is_also_artist && !is_also_album_artist {
let artist = self.get_or_create_artist(*name);
artist.composer_credits.insert(album_key.clone());
}
}
for name in &song.lyricists {
let is_also_artist = song.artists.contains(name);
let is_also_album_artist = song.artists.contains(name);
if !is_also_artist && !is_also_album_artist {
let artist = self.get_or_create_artist(*name);
artist.lyricist_credits.insert(album_key.clone());
}
}
}
@ -218,7 +262,9 @@ impl Builder {
.or_insert_with(|| storage::Artist {
name: Some(name),
albums: HashSet::new(),
album_appearances: HashSet::new(),
song_credits: HashSet::new(),
composer_credits: HashSet::new(),
lyricist_credits: HashSet::new(),
})
.borrow_mut()
}

View file

@ -3,7 +3,7 @@ use std::{
path::{Path, PathBuf},
};
use lasso2::{RodeoReader, Rodeo};
use lasso2::{Rodeo, RodeoReader};
use log::error;
use serde::{Deserialize, Serialize};
use tinyvec::TinyVec;
@ -20,7 +20,9 @@ pub enum File {
pub struct Artist {
pub name: Option<lasso2::Spur>,
pub albums: HashSet<AlbumKey>,
pub album_appearances: HashSet<AlbumKey>,
pub song_credits: HashSet<AlbumKey>,
pub composer_credits: HashSet<AlbumKey>,
pub lyricist_credits: HashSet<AlbumKey>,
}
#[derive(Clone, Default, Serialize, Deserialize)]

View file

@ -310,7 +310,9 @@ impl From<index::File> for BrowserEntry {
pub struct Artist {
pub name: Option<String>,
pub albums: Vec<AlbumHeader>,
pub album_appearances: Vec<AlbumHeader>,
pub song_credits: Vec<AlbumHeader>,
pub composer_credits: Vec<AlbumHeader>,
pub lyricist_credits: Vec<AlbumHeader>,
}
impl From<index::Artist> for Artist {
@ -318,7 +320,9 @@ impl From<index::Artist> for Artist {
Self {
name: a.name,
albums: a.albums.into_iter().map(|a| a.into()).collect(),
album_appearances: a.album_appearances.into_iter().map(|a| a.into()).collect(),
song_credits: a.song_credits.into_iter().map(|a| a.into()).collect(),
composer_credits: a.composer_credits.into_iter().map(|a| a.into()).collect(),
lyricist_credits: a.lyricist_credits.into_iter().map(|a| a.into()).collect(),
}
}
}