From e5838dc55c8c3da2d222f68ea60a23fbd0480273 Mon Sep 17 00:00:00 2001 From: Artem Bulgakov Date: Sat, 23 Nov 2024 00:34:33 +0300 Subject: [PATCH] fix: filters logic --- backend/src/modules/events/repository.py | 56 +++++++++++++++++++----- 1 file changed, 44 insertions(+), 12 deletions(-) diff --git a/backend/src/modules/events/repository.py b/backend/src/modules/events/repository.py index fda8032..938603a 100644 --- a/backend/src/modules/events/repository.py +++ b/backend/src/modules/events/repository.py @@ -1,7 +1,8 @@ __all__ = ["events_repository"] from beanie import SortDirection -from beanie.odm.operators.find.comparison import In +from beanie.odm.operators.find.comparison import GTE, LTE, Eq, In +from beanie.odm.operators.find.logical import And, Or from src.modules.events.schemas import Filters, Pagination, Sort from src.storages.mongo.events import Event @@ -25,16 +26,33 @@ async def read_with_filters(self, filters: Filters, sort: Sort, pagination: Pagi query = Event.all() # Apply filters - if filters.age and filters.age.min is not None: - query = query.find(Event.age_max >= filters.age.min) - if filters.age and filters.age.max is not None: - query = query.find(Event.age_min <= filters.age.max) - if filters.participant_count and filters.participant_count.min is not None: - query = query.find(Event.participant_count >= filters.participant_count.min) - if filters.participant_count and filters.participant_count.max is not None: - query = query.find(Event.participant_count <= filters.participant_count.max) + if filters.age: + # FIXME: Может работать неверно, если у событий не указан возраст + filters.age.min = filters.age.min or 0 + filters.age.max = filters.age.max or 100 + query = query.find( + (filters.age.min <= Event.age_min <= filters.age.max) + or (filters.age.min <= Event.age_max <= filters.age.max) + or (filters.age.min >= Event.age_min and Event.age_max <= filters.age.max) + or (filters.age.min >= Event.age_min and filters.age.max <= Event.age_max) + or (Event.age_min == None and Event.age_max >= filters.age.min) # noqa: E711 + or (Event.age_min == None and Event.age_max >= filters.age.max) # noqa: E711 + or (Event.age_max == None and Event.age_min <= filters.age.min) # noqa: E711 + or (Event.age_max == None and Event.age_min <= filters.age.max) # noqa: E711 + or (Event.age_min == None and Event.age_max == None) # noqa: E711 + ) + if filters.participant_count: + if filters.participant_count.min is not None and filters.participant_count.max is not None: + query = query.find( + GTE(Event.participant_count, filters.participant_count.min), + LTE(Event.participant_count, filters.participant_count.max), + ) + elif filters.participant_count.min is not None: + query = query.find(GTE(Event.participant_count, filters.participant_count.min)) + elif filters.participant_count.max is not None: + query = query.find(LTE(Event.participant_count, filters.participant_count.max)) if filters.gender is not None: - query = query.find(Event.gender == filters.gender) + query = query.find(Or(Event.gender == filters.gender, Event.gender == None)) # noqa: E711 if filters.date and filters.date.start_date is not None: query = query.find(Event.start_date >= filters.date.start_date) if filters.date and filters.date.end_date is not None: @@ -46,8 +64,22 @@ async def read_with_filters(self, filters: Filters, sort: Sort, pagination: Pagi query = query.find(In(Event.discipline, [discipline.discipline for discipline in filters.discipline])) if filters.location: - # TODO: Проверить - query = query.find(In(Event.location, filters.location)) + conditions = [] + for loc in filters.location: + if loc.region is None and loc.city is None: + conditions.append(Eq("location.country", loc.country)) + elif loc.city is None: + conditions.append(And(Eq("location.country", loc.country), Eq("location.region", loc.region))) + else: + conditions.append( + And( + Eq("location.country", loc.country), + Eq("location.region", loc.region), + Eq("location.city", loc.city), + ) + ) + if conditions: + query = query.find(Or(*conditions)) if filters.query: query = query.find({"$text": {"$search": filters.query}})