move to xxh3 hashing algorithm

+ port: search
This commit is contained in:
cwilvx
2024-07-03 11:12:06 +03:00
parent ff7343a7be
commit a5634f267f
16 changed files with 322 additions and 182 deletions
+50 -20
View File
@@ -14,7 +14,7 @@ from app.models import Album as AlbumModel
from app.utils.remove_duplicates import remove_duplicates
from app.db import engine
from sqlalchemy import JSON, Boolean, Integer, String, and_, delete, select, update
from sqlalchemy import JSON, Boolean, Integer, String, delete, select, update
from sqlalchemy.orm import Mapped, mapped_column, DeclarativeBase
@@ -32,16 +32,26 @@ class Base(MasterBase, DeclarativeBase):
@classmethod
def get_all_hashes(cls, create_date: int | None = None):
with DbManager() as conn:
if cls.__tablename__ == "track":
stmt = select(TrackTable.trackhash).where(cls.last_mod < create_date)
elif cls.__tablename__ == "album":
stmt = select(AlbumTable.albumhash).where(
cls.created_date < create_date
)
elif cls.__tablename__ == "artist":
stmt = select(ArtistTable.artisthash).where(
cls.created_date < create_date
)
if create_date:
if cls.__tablename__ == "track":
stmt = select(TrackTable.trackhash).where(
cls.last_mod < create_date
)
elif cls.__tablename__ == "album":
stmt = select(AlbumTable.albumhash).where(
cls.created_date < create_date
)
elif cls.__tablename__ == "artist":
stmt = select(ArtistTable.artisthash).where(
cls.created_date < create_date
)
else:
if cls.__tablename__ == "track":
stmt = select(TrackTable.trackhash)
elif cls.__tablename__ == "album":
stmt = select(AlbumTable.albumhash)
elif cls.__tablename__ == "artist":
stmt = select(ArtistTable.artisthash)
result = conn.execute(stmt)
return {row[0] for row in result.fetchall()}
@@ -135,7 +145,9 @@ class TrackTable(Base):
def get_tracks_by_filepaths(cls, filepaths: list[str]):
with DbManager() as conn:
result = conn.execute(
select(TrackTable).where(TrackTable.filepath.in_(filepaths))
select(TrackTable)
.where(TrackTable.filepath.in_(filepaths))
.order_by(TrackTable.last_mod)
)
return tracks_to_dataclasses(result.fetchall())
@@ -155,10 +167,8 @@ class TrackTable(Base):
result = conn.execute(
select(TrackTable)
.where(
and_(
TrackTable.trackhash == hash,
TrackTable.filepath == filepath,
)
(TrackTable.trackhash == hash)
& (TrackTable.filepath == filepath),
)
.order_by(TrackTable.bitrate.desc())
)
@@ -194,9 +204,18 @@ class TrackTable(Base):
def get_tracks_by_trackhashes(cls, hashes: Iterable[str], limit: int | None = None):
with DbManager() as conn:
result = conn.execute(
select(TrackTable).where(TrackTable.trackhash.in_(hashes)).limit(limit)
select(TrackTable)
.where(TrackTable.trackhash.in_(hashes))
.group_by(TrackTable.trackhash)
.limit(limit)
)
return tracks_to_dataclasses(result.fetchall())
tracks = tracks_to_dataclasses(result.fetchall())
# order the tracks in the same order as the hashes
if type(hashes) == list:
return sorted(tracks, key=lambda x: hashes.index(x.trackhash))
return tracks
@classmethod
def get_recently_added(cls, start: int, limit: int):
@@ -212,7 +231,12 @@ class TrackTable(Base):
@classmethod
def get_recently_played(cls, limit: int):
result = cls.execute(select(cls).order_by(cls.lastplayed.desc()).limit(limit))
result = cls.execute(
select(cls)
.group_by(cls.trackhash)
.order_by(cls.lastplayed.desc())
.limit(limit)
)
return tracks_to_dataclasses(result.fetchall())
@classmethod
@@ -276,7 +300,13 @@ class AlbumTable(Base):
result = conn.execute(
select(AlbumTable).where(AlbumTable.albumhash.in_(hashes)).limit(limit)
)
return albums_to_dataclasses(result.fetchall())
albums = albums_to_dataclasses(result.fetchall())
# order the albums in the same order as the hashes
if type(hashes) == list:
return sorted(albums, key=lambda x: hashes.index(x.albumhash))
return albums
@classmethod
def get_albums_by_artisthashes(cls, artisthashes: list[str]):
+50 -14
View File
@@ -1,7 +1,7 @@
import datetime
import enum
from shlex import join
from typing import Any
from flask_jwt_extended import current_user
from sqlalchemy import (
JSON,
Boolean,
@@ -313,36 +313,41 @@ class PlaylistTable(Base):
@classmethod
def append_to_playlist(cls, id: int, trackhashes: list[str]):
print("type(trackhashes):", type(trackhashes))
dbtrackhashes = cls.get_trackhashes(id)
if not dbtrackhashes:
dbtrackhashes = []
return cls.execute(
update(cls)
.where((cls.id == id) & (cls.userid == get_current_userid()))
.values(trackhashes=cls.trackhashes + trackhashes),
.values(trackhashes=dbtrackhashes + trackhashes),
commit=True,
)
@classmethod
def remove_from_playlist(cls, id: int, trackhashes: list[dict[str, Any]]):
# CHECKPOINT: Properly remove tracks from a playlist
# Without messing up the order in case of duplicates
tracks = cls.execute(
def get_trackhashes(cls, id: int) -> list[str]:
result = cls.execute(
select(cls.trackhashes).where(
(cls.id == id) & (cls.userid == get_current_userid())
)
)
result = result.fetchone()
if result:
return result[0]
results = tracks.fetchone()
if results:
dbhashes: list[str] = results[0]
@classmethod
def remove_from_playlist(cls, id: int, trackhashes: list[dict[str, Any]]):
# INFO: Get db trackhashes
dbtrackhashes = cls.get_trackhashes(id)
if dbtrackhashes:
for item in trackhashes:
if dbhashes.index(item["trackhash"]) == item["index"]:
dbhashes.remove(item["trackhash"])
if dbtrackhashes.index(item["trackhash"]) == item["index"]:
dbtrackhashes.remove(item["trackhash"])
return cls.execute(
update(cls)
.where((cls.id == id) & (cls.userid == get_current_userid()))
.values(trackhashes=dbhashes),
.values(trackhashes=dbtrackhashes),
commit=True,
)
@@ -381,3 +386,34 @@ class PlaylistTable(Base):
.values(image=None),
commit=True,
)
# class PlaylistTrackTable(Base):
# __tablename__ = "playlisttrack"
# id: Mapped[int] = mapped_column(primary_key=True)
# trackhash: Mapped[str] = mapped_column(String(), index=True)
# playlistid: Mapped[int] = mapped_column(
# Integer(), ForeignKey("playlist.id", ondelete="cascade")
# )
# index: Mapped[int] = mapped_column(Integer())
# userid: Mapped[int] = mapped_column(
# Integer(), ForeignKey("user.id", ondelete="cascade")
# )
# @classmethod
# def count_by_playlist()
# @classmethod
# def insert_many(cls, playlistid: int, trackhashes: list[str]):
# userid = get_current_userid()
# items = [
# {
# "index": index,
# "userid": userid,
# "trackhash": trackhash,
# "playlistid": playlistid,
# }
# for index, trackhash in enumerate(trackhashes)
# ]
# return cls.execute(insert(cls).values(items), commit=True)