Update random objects getter

This commit is contained in:
2022-01-01 12:37:22 +03:00
parent a58136c5c2
commit 4a78d4f987
7 changed files with 49 additions and 15 deletions

View File

@@ -1,6 +1,6 @@
from app.models import Author from app.models import Author
from app.services.common import TRGMSearchService from app.services.common import TRGMSearchService, GetRandomService
GET_OBJECT_IDS_QUERY = """ GET_OBJECT_IDS_QUERY = """
@@ -41,3 +41,7 @@ class AuthorTGRMSearchService(TRGMSearchService):
MODEL_CLASS = Author MODEL_CLASS = Author
PREFETCH_RELATED = ["source", "annotations"] PREFETCH_RELATED = ["source", "annotations"]
GET_OBJECT_IDS_QUERY = GET_OBJECT_IDS_QUERY GET_OBJECT_IDS_QUERY = GET_OBJECT_IDS_QUERY
class GetRandomAuthorService(GetRandomService):
MODEL_CLASS = Author

View File

@@ -4,7 +4,7 @@ from fastapi import HTTPException, status
from app.models import Book as BookDB, Author as AuthorDB from app.models import Book as BookDB, Author as AuthorDB
from app.services.common import TRGMSearchService from app.services.common import TRGMSearchService, GetRandomService
from app.serializers.book import CreateBook, CreateRemoteBook from app.serializers.book import CreateBook, CreateRemoteBook
@@ -76,3 +76,7 @@ class BookCreator:
return await cls._create_book(data) return await cls._create_book(data)
if isinstance(data, CreateRemoteBook): if isinstance(data, CreateRemoteBook):
return await cls._create_remote_book(data) return await cls._create_remote_book(data)
class GetRandomBookService(GetRandomService):
MODEL_CLASS = BookDB

View File

@@ -122,3 +122,31 @@ class TRGMSearchService(Generic[T]):
total=total, total=total,
params=params params=params
) )
GET_RANDOM_OBJECT_ID_QUERY = """
SELECT id FROM {table}
WHERE id >= RANDOM() * (SELECT MAX(id) FROM {table})
ORDER BY id LIMIT 1;
"""
class GetRandomService(Generic[T]):
MODEL_CLASS: Optional[T] = None
@classmethod
@property
def model(cls) -> T:
assert cls.MODEL_CLASS is not None, f"MODEL in {cls.__name__} don't set!"
return cls.MODEL_CLASS
@classmethod
@property
def database(cls) -> Database:
return cls.model.Meta.database
@classmethod
async def get_random_id(cls) -> int:
table_name = cls.model.Meta.tablename
query = GET_RANDOM_OBJECT_ID_QUERY.format(table=table_name)
return await cls.database.fetch_val(query)

View File

@@ -1,6 +1,6 @@
from app.models import Sequence from app.models import Sequence
from app.services.common import TRGMSearchService from app.services.common import TRGMSearchService, GetRandomService
GET_OBJECT_IDS_QUERY = """ GET_OBJECT_IDS_QUERY = """
@@ -33,3 +33,7 @@ class SequenceTGRMSearchService(TRGMSearchService):
MODEL_CLASS = Sequence MODEL_CLASS = Sequence
PREFETCH_RELATED = ["source"] PREFETCH_RELATED = ["source"]
GET_OBJECT_IDS_QUERY = GET_OBJECT_IDS_QUERY GET_OBJECT_IDS_QUERY = GET_OBJECT_IDS_QUERY
class GetRandomSequenceService(GetRandomService):
MODEL_CLASS = Sequence

View File

@@ -9,7 +9,7 @@ from app.utils.pagination import CustomPage
from app.models import Author as AuthorDB, AuthorAnnotation as AuthorAnnotationDB, Book as BookDB from app.models import Author as AuthorDB, AuthorAnnotation as AuthorAnnotationDB, Book as BookDB
from app.serializers.author import Author, CreateAuthor, UpdateAuthor, AuthorBook, TranslatedBook from app.serializers.author import Author, CreateAuthor, UpdateAuthor, AuthorBook, TranslatedBook
from app.serializers.author_annotation import AuthorAnnotation from app.serializers.author_annotation import AuthorAnnotation
from app.services.author import AuthorTGRMSearchService from app.services.author import AuthorTGRMSearchService, GetRandomAuthorService
from app.depends import check_token from app.depends import check_token
@@ -42,9 +42,7 @@ async def create_author(data: CreateAuthor):
@author_router.get("/random", response_model=Author) @author_router.get("/random", response_model=Author)
async def get_random_author(): async def get_random_author():
author_ids: list[int] = await AuthorDB.objects.values_list("id", flatten=True) author_id = await GetRandomAuthorService.get_random_id()
author_id = random_choice(author_ids)
return await AuthorDB.objects.prefetch_related(PREFETCH_RELATED).get(id=author_id) return await AuthorDB.objects.prefetch_related(PREFETCH_RELATED).get(id=author_id)

View File

@@ -10,7 +10,7 @@ from app.utils.pagination import CustomPage
from app.models import Book as BookDB, Author as AuthorDB, BookAnnotation as BookAnnotationDB from app.models import Book as BookDB, Author as AuthorDB, BookAnnotation as BookAnnotationDB
from app.serializers.book import Book, RemoteBook, BookDetail, CreateBook, UpdateBook, CreateRemoteBook from app.serializers.book import Book, RemoteBook, BookDetail, CreateBook, UpdateBook, CreateRemoteBook
from app.serializers.book_annotation import BookAnnotation from app.serializers.book_annotation import BookAnnotation
from app.services.book import BookTGRMSearchService, BookCreator from app.services.book import BookTGRMSearchService, GetRandomBookService, BookCreator
from app.filters.book import get_book_filter from app.filters.book import get_book_filter
from app.depends import check_token from app.depends import check_token
@@ -41,9 +41,7 @@ async def create_book(data: Union[CreateBook, CreateRemoteBook]):
@book_router.get("/random", response_model=BookDetail) @book_router.get("/random", response_model=BookDetail)
async def get_random_book(): async def get_random_book():
book_ids: list[int] = await BookDB.objects.filter(is_deleted=False).values_list("id", flatten=True) book_id = await GetRandomBookService.get_random_id()
book_id = random_choice(book_ids)
return await BookDB.objects.select_related(SELECT_RELATED_FIELDS).get(id=book_id) return await BookDB.objects.select_related(SELECT_RELATED_FIELDS).get(id=book_id)

View File

@@ -8,7 +8,7 @@ from app.utils.pagination import CustomPage
from app.models import Sequence as SequenceDB, Book as BookDB, BookSequences as BookSequencesDB from app.models import Sequence as SequenceDB, Book as BookDB, BookSequences as BookSequencesDB
from app.serializers.sequence import Sequence, CreateSequence, Book as SequenceBook from app.serializers.sequence import Sequence, CreateSequence, Book as SequenceBook
from app.services.sequence import SequenceTGRMSearchService from app.services.sequence import SequenceTGRMSearchService, GetRandomSequenceService
from app.depends import check_token from app.depends import check_token
@@ -28,9 +28,7 @@ async def get_sequences():
@sequence_router.get("/random", response_model=Sequence) @sequence_router.get("/random", response_model=Sequence)
async def get_random_sequence(): async def get_random_sequence():
sequence_ids: list[int] = await SequenceDB.objects.values_list("id", flatten=True) sequence_id = await GetRandomSequenceService.get_random_id()
sequence_id = random_choice(sequence_ids)
return await SequenceDB.objects.get(id=sequence_id) return await SequenceDB.objects.get(id=sequence_id)