This commit is contained in:
2022-04-02 16:36:57 +03:00
parent 6788a1de02
commit 2fa9c691fe
4 changed files with 34 additions and 23 deletions

View File

@@ -48,7 +48,7 @@ class AuthorTGRMSearchService(TRGMSearchService):
GET_OBJECT_IDS_QUERY = GET_OBJECT_IDS_QUERY GET_OBJECT_IDS_QUERY = GET_OBJECT_IDS_QUERY
GET_RANDOM_OBJECT_ID_QUERY = """ GET_OBJECT_ID_QUERY = """
WITH filtered_authors AS ( WITH filtered_authors AS (
SELECT id FROM authors SELECT id FROM authors
WHERE EXISTS ( WHERE EXISTS (
@@ -58,14 +58,13 @@ WITH filtered_authors AS (
AND books.lang = ANY(:langs ::text[]) AND books.lang = ANY(:langs ::text[])
) )
) )
SELECT id FROM filtered_authors SELECT id FROM filtered_authors;
ORDER BY RANDOM() LIMIT 1;
""" """
class GetRandomAuthorService(GetRandomService): class GetRandomAuthorService(GetRandomService):
MODEL_CLASS = Author MODEL_CLASS = Author
GET_RANDOM_OBJECT_ID_QUERY = GET_RANDOM_OBJECT_ID_QUERY GET_OBJECT_ID_QUERY = GET_OBJECT_ID_QUERY
class AuthorMeiliSearchService(MeiliSearchService): class AuthorMeiliSearchService(MeiliSearchService):

View File

@@ -89,19 +89,18 @@ class BookCreator:
return await cls._create_remote_book(data) return await cls._create_remote_book(data)
GET_RANDOM_OBJECT_ID_QUERY = """ GET_OBJECTS_ID_QUERY = """
WITH filtered_books AS ( WITH filtered_books AS (
SELECT id FROM books SELECT id FROM books
WHERE books.is_deleted = 'f' AND books.lang = ANY(:langs ::text[]) WHERE books.is_deleted = 'f' AND books.lang = ANY(:langs ::text[])
) )
SELECT id FROM filtered_books SELECT id FROM filtered_books;
ORDER BY RANDOM() LIMIT 1;
""" """
class GetRandomBookService(GetRandomService): class GetRandomBookService(GetRandomService):
MODEL_CLASS = BookDB MODEL_CLASS = BookDB
GET_RANDOM_OBJECT_ID_QUERY = GET_RANDOM_OBJECT_ID_QUERY GET_OBJECT_ID_QUERY = GET_OBJECT_IDS_QUERY
class BookMeiliSearchService(MeiliSearchService): class BookMeiliSearchService(MeiliSearchService):

View File

@@ -1,6 +1,7 @@
import abc import abc
import asyncio import asyncio
from concurrent.futures import ThreadPoolExecutor from concurrent.futures import ThreadPoolExecutor
from random import choice
from typing import Optional, Generic, TypeVar, TypedDict, Union from typing import Optional, Generic, TypeVar, TypedDict, Union
import aioredis import aioredis
@@ -102,11 +103,7 @@ class BaseSearchService(Generic[MODEL, QUERY], abc.ABC):
print(e) print(e)
@classmethod @classmethod
async def get_objects( async def _get_objects(cls, query: QUERY, redis: aioredis.Redis) -> list[int]:
cls, query: QUERY, redis: aioredis.Redis
) -> tuple[int, list[MODEL]]:
params = cls.get_raw_params()
cached_object_ids = await cls.get_cached_ids(query, redis) cached_object_ids = await cls.get_cached_ids(query, redis)
if cached_object_ids is None: if cached_object_ids is None:
@@ -115,6 +112,16 @@ class BaseSearchService(Generic[MODEL, QUERY], abc.ABC):
else: else:
object_ids = cached_object_ids object_ids = cached_object_ids
return object_ids
@classmethod
async def get_limited_objects(
cls, query: QUERY, redis: aioredis.Redis
) -> tuple[int, list[MODEL]]:
object_ids = await cls._get_objects(query, redis)
params = cls.get_raw_params()
limited_object_ids = object_ids[params.offset : params.offset + params.limit] limited_object_ids = object_ids[params.offset : params.offset + params.limit]
queryset: QuerySet[MODEL] = cls.model.objects queryset: QuerySet[MODEL] = cls.model.objects
@@ -134,7 +141,7 @@ class BaseSearchService(Generic[MODEL, QUERY], abc.ABC):
async def get(cls, query: QUERY, redis: aioredis.Redis) -> Page[MODEL]: async def get(cls, query: QUERY, redis: aioredis.Redis) -> Page[MODEL]:
params = cls.get_params() params = cls.get_params()
total, objects = await cls.get_objects(query, redis) total, objects = await cls.get_limited_objects(query, redis)
return CustomPage.create(items=objects, total=total, params=params) return CustomPage.create(items=objects, total=total, params=params)
@@ -229,7 +236,7 @@ class MeiliSearchService(Generic[MODEL], BaseSearchService[MODEL, SearchQuery]):
class GetRandomService(Generic[MODEL]): class GetRandomService(Generic[MODEL]):
MODEL_CLASS: Optional[MODEL] = None MODEL_CLASS: Optional[MODEL] = None
GET_RANDOM_OBJECT_ID_QUERY: Optional[str] = None GET_OBJECTS_ID_QUERY: Optional[str] = None
@classmethod @classmethod
@property @property
@@ -244,17 +251,23 @@ class GetRandomService(Generic[MODEL]):
@classmethod @classmethod
@property @property
def random_object_id_query(cls) -> str: def objects_id_query(cls) -> str:
assert ( assert (
cls.GET_RANDOM_OBJECT_ID_QUERY is not None cls.GET_OBJECTS_ID_QUERY is not None
), f"GET_OBJECT_IDS_QUERY in {cls.__name__} don't set!" ), f"GET_OBJECT_IDS_QUERY in {cls.__name__} don't set!"
return cls.GET_RANDOM_OBJECT_ID_QUERY return cls.GET_OBJECTS_ID_QUERY
@classmethod
async def get_objects(cls, allowed_langs: frozenset[str]) -> list[int]:
objects = await cls.database.fetch_all(
cls.objects_id_query, {"langs": allowed_langs}
)
return [obj["id"] for obj in objects]
@classmethod @classmethod
async def get_random_id(cls, allowed_langs: frozenset[str]) -> int: async def get_random_id(cls, allowed_langs: frozenset[str]) -> int:
return await cls.database.fetch_val( object_ids = await cls.get_objects(allowed_langs)
cls.random_object_id_query, {"langs": allowed_langs} return choice(object_ids)
)
class BaseFilterService(Generic[MODEL, QUERY], BaseSearchService[MODEL, QUERY]): class BaseFilterService(Generic[MODEL, QUERY], BaseSearchService[MODEL, QUERY]):

View File

@@ -36,7 +36,7 @@ class SequenceTGRMSearchService(TRGMSearchService):
GET_OBJECT_IDS_QUERY = GET_OBJECT_IDS_QUERY GET_OBJECT_IDS_QUERY = GET_OBJECT_IDS_QUERY
GET_RANDOM_OBJECT_ID_QUERY = """ GET_OBJECT_ID_QUERY = """
WITH filtered_sequences AS ( WITH filtered_sequences AS (
SELECT id FROM sequences SELECT id FROM sequences
WHERE EXISTS ( WHERE EXISTS (
@@ -55,7 +55,7 @@ ORDER BY RANDOM() LIMIT 1;
class GetRandomSequenceService(GetRandomService): class GetRandomSequenceService(GetRandomService):
MODEL_CLASS = Sequence MODEL_CLASS = Sequence
GET_RANDOM_OBJECT_ID_QUERY = GET_RANDOM_OBJECT_ID_QUERY GET_OBJECT_ID_QUERY = GET_OBJECT_ID_QUERY
class SequenceMeiliSearchService(MeiliSearchService): class SequenceMeiliSearchService(MeiliSearchService):