mirror of
https://github.com/flibusta-apps/book_library_server.git
synced 2025-12-06 07:05:36 +01:00
99 lines
2.7 KiB
Python
99 lines
2.7 KiB
Python
from typing import Optional, TypedDict
|
|
|
|
from app.models import Book as BookDB
|
|
from app.services.common import (
|
|
BaseFilterService,
|
|
GetRandomService,
|
|
MeiliSearchService,
|
|
TRGMSearchService,
|
|
)
|
|
|
|
|
|
GET_OBJECT_IDS_QUERY = """
|
|
SELECT ARRAY(
|
|
WITH filtered_books AS (
|
|
SELECT id, similarity(title, :query) as sml FROM books
|
|
WHERE books.title % :query AND books.is_deleted = 'f'
|
|
AND books.lang = ANY(:langs ::text[])
|
|
)
|
|
SELECT fbooks.id FROM filtered_books as fbooks
|
|
ORDER BY fbooks.sml DESC, fbooks.id
|
|
LIMIT 210
|
|
);
|
|
"""
|
|
|
|
|
|
class BookTGRMSearchService(TRGMSearchService):
|
|
MODEL_CLASS = BookDB
|
|
PREFETCH_RELATED = ["source"]
|
|
SELECT_RELATED = ["authors", "translators", "annotations"]
|
|
|
|
GET_OBJECT_IDS_QUERY = GET_OBJECT_IDS_QUERY
|
|
|
|
|
|
class BookBaseInfoFilterService(BaseFilterService):
|
|
MODEL_CLASS = BookDB
|
|
PREFETCH_RELATED = []
|
|
SELECT_RELATED = []
|
|
|
|
|
|
class BookFilterService(BaseFilterService):
|
|
MODEL_CLASS = BookDB
|
|
PREFETCH_RELATED = ["source"]
|
|
SELECT_RELATED = ["authors", "translators", "annotations"]
|
|
|
|
|
|
GET_OBJECTS_ID_QUERY = """
|
|
WITH filtered_books AS (
|
|
SELECT id FROM books
|
|
WHERE books.is_deleted = 'f' AND books.lang = ANY(:langs ::text[])
|
|
)
|
|
SELECT id FROM filtered_books;
|
|
"""
|
|
|
|
|
|
GET_OBJECTS_ID_BY_GENRE_QUERY = """
|
|
WITH filtered_books AS (
|
|
SELECT books.id FROM books
|
|
LEFT JOIN book_genres ON (book_genres.book = books.id)
|
|
WHERE books.is_deleted = 'f' AND book_genres.genre = :genre
|
|
AND books.lang = ANY(:langs ::text[])
|
|
)
|
|
SELECT id FROM filtered_books;
|
|
"""
|
|
|
|
|
|
class RandomBookServiceQuery(TypedDict):
|
|
genre: Optional[int]
|
|
allowed_langs: frozenset[str]
|
|
|
|
|
|
class GetRandomBookService(GetRandomService[BookDB, RandomBookServiceQuery]):
|
|
MODEL_CLASS = BookDB # type: ignore
|
|
PREFETCH_RELATED = ["source"]
|
|
SELECT_RELATED = ["authors", "translators", "annotations"]
|
|
|
|
GET_OBJECTS_ID_QUERY = GET_OBJECTS_ID_QUERY
|
|
GET_OBJECTS_ID_BY_GENRE_QUERY = GET_OBJECTS_ID_BY_GENRE_QUERY
|
|
|
|
@classmethod
|
|
async def _get_objects_from_db(cls, query: RandomBookServiceQuery) -> list[int]:
|
|
if query.get("genre") is None:
|
|
ex_query = cls.objects_id_query
|
|
params = {"langs": query["allowed_langs"]}
|
|
else:
|
|
ex_query = cls.GET_OBJECTS_ID_BY_GENRE_QUERY
|
|
params = {"langs": query["allowed_langs"], "genre": query["genre"]}
|
|
|
|
objects = await cls.database.fetch_all(ex_query, params)
|
|
return [obj["id"] for obj in objects]
|
|
|
|
|
|
class BookMeiliSearchService(MeiliSearchService):
|
|
MODEL_CLASS = BookDB
|
|
PREFETCH_RELATED = ["source"]
|
|
SELECT_RELATED = ["authors", "translators", "annotations", "sequences"]
|
|
|
|
MS_INDEX_NAME = "books"
|
|
MS_INDEX_LANG_KEY = "lang"
|