From bb700d26f1381a343ea19325877c72bf735cadb9 Mon Sep 17 00:00:00 2001 From: Keith Edmunds Date: Wed, 4 Oct 2023 01:50:51 +0100 Subject: [PATCH] Faster track selection diaglog Use better query to load last_played times along with tracks --- app/models.py | 18 +++++++++++++----- app/musicmuster.py | 18 +++++++++--------- 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/app/models.py b/app/models.py index 78185df..d746ccf 100644 --- a/app/models.py +++ b/app/models.py @@ -25,6 +25,7 @@ from sqlalchemy import ( from sqlalchemy.orm import ( declarative_base, + joinedload, relationship, ) from sqlalchemy.orm.exc import ( @@ -133,7 +134,7 @@ class Playdates(Base): __tablename__ = "playdates" id: int = Column(Integer, primary_key=True, autoincrement=True) - lastplayed = Column(DateTime, index=True, default=None) + lastplayed: datetime = Column(DateTime, index=True) track_id = Column(Integer, ForeignKey("tracks.id")) track: "Tracks" = relationship("Tracks", back_populates="playdates") @@ -638,9 +639,9 @@ class Tracks(Base): path: str = Column(String(2048), index=False, nullable=False, unique=True) mtime = Column(Float, index=True) bitrate = Column(Integer, nullable=True, default=None) - playlistrows: PlaylistRows = relationship("PlaylistRows", back_populates="track") + playlistrows: List[PlaylistRows] = relationship("PlaylistRows", back_populates="track") playlists = association_proxy("playlistrows", "playlist") - playdates: Playdates = relationship("Playdates", back_populates="track") + playdates: List[Playdates] = relationship("Playdates", back_populates="track") def __repr__(self) -> str: return ( @@ -715,15 +716,22 @@ class Tracks(Base): @classmethod def search_titles(cls, session: scoped_session, text: str) -> List["Tracks"]: - """Search case-insenstively for titles containing str""" + """ + Search case-insenstively for titles containing str + + The query performs an outer join with 'joinedload' to populate the results + from the Playdates table at the same time. unique() needed; see + https://docs.sqlalchemy.org/en/20/orm/queryguide/relationships.html#joined-eager-loading + """ return ( session.execute( select(cls) - .join(Playdates, isouter=True) + .options(joinedload(Tracks.playdates)) .where(cls.title.like(f"{text}%")) .group_by(cls.title) .order_by(cls.title) ) .scalars() + .unique() .all() ) diff --git a/app/musicmuster.py b/app/musicmuster.py index 7d9b3c5..b5eaad0 100755 --- a/app/musicmuster.py +++ b/app/musicmuster.py @@ -1937,7 +1937,9 @@ class DbDialog(QDialog): return if track: - self.musicmuster.visible_playlist_tab().insert_track(self.session, track, note) + self.musicmuster.visible_playlist_tab().insert_track( + self.session, track, note + ) else: self.musicmuster.visible_playlist_tab().insert_header(self.session, note) @@ -1956,19 +1958,17 @@ class DbDialog(QDialog): if matches: for track in matches: last_played = None - show_last_played = False - if len(matches) < 20: - show_last_played = True - last_playdate = max(track.playdates, key=lambda p: p.lastplayed, default=None) - if last_playdate: - last_played = last_playdate.lastplayed + last_playdate = max( + track.playdates, key=lambda p: p.lastplayed, default=None + ) + if last_playdate: + last_played = last_playdate.lastplayed t = QListWidgetItem() track_text = ( f"{track.title} - {track.artist} " f"[{helpers.ms_to_mmss(track.duration)}] " + f"({helpers.get_relative_date(last_played)})" ) - if show_last_played: - track_text += f"({helpers.get_relative_date(last_played)})" t.setText(track_text) t.setData(Qt.ItemDataRole.UserRole, track) self.ui.matchList.addItem(t)