diff --git a/api/chalicelib/core/sessions/sessions_ch.py b/api/chalicelib/core/sessions/sessions_ch.py index e86843f1a..f485e1e7a 100644 --- a/api/chalicelib/core/sessions/sessions_ch.py +++ b/api/chalicelib/core/sessions/sessions_ch.py @@ -660,7 +660,8 @@ def search_query_parts_ch(data: schemas.SessionsSearchPayloadSchema, error_statu event.value = helper.values_for_operator(value=event.value, op=event.operator) full_args = {**full_args, **sh.multi_values(event.value, value_key=e_k), - **sh.multi_values(event.source, value_key=s_k)} + **sh.multi_values(event.source, value_key=s_k), + e_k: event.value[0] if len(event.value) > 0 else event.value} if event_type == events.EventType.CLICK.ui_type: event_from = event_from % f"{MAIN_EVENTS_TABLE} AS main " @@ -1206,10 +1207,16 @@ def search_query_parts_ch(data: schemas.SessionsSearchPayloadSchema, error_statu else: logging.warning(f"undefined GRAPHQL filter: {f.type}") events_conditions[-1]["condition"] = " AND ".join(events_conditions[-1]["condition"]) + elif event_type == schemas.EventType.EVENT: + event_from = event_from % f"{MAIN_EVENTS_TABLE} AS main " + _column = events.EventType.CLICK.column + event_where.append(f"main.`$event_name`=%({e_k})s") + events_conditions.append({"type": event_where[-1], "condition": ""}) + else: continue if event.properties is not None and len(event.properties.filters) > 0: - event_fiters = [] + sub_conditions = [] for l, property in enumerate(event.properties.filters): a_k = f"{e_k}_att_{l}" full_args = {**full_args, @@ -1221,15 +1228,11 @@ def search_query_parts_ch(data: schemas.SessionsSearchPayloadSchema, error_statu event_where.append( sh.multi_conditions(condition, property.value, value_key=a_k) ) - event_fiters.append(event_where[-1]) - if len(event_fiters) > 0: - events_conditions[-1]["condition"] += " AND (" - for l, e_f in enumerate(event_fiters): - if l > 0: - events_conditions[-1]["condition"] += event.properties.operators[l - 1] + e_f - else: - events_conditions[-1]["condition"] += e_f - events_conditions[-1]["condition"] += ")" + sub_conditions.append(event_where[-1]) + if len(sub_conditions) > 0: + sub_conditions = (" " + event.properties.operator + " ").join(sub_conditions) + events_conditions[-1]["condition"] += " AND " if len(events_conditions[-1]["condition"]) > 0 else "" + events_conditions[-1]["condition"] += "(" + sub_conditions + ")" if event_index == 0 or or_events: event_where += ss_constraints if is_not: diff --git a/api/schemas/schemas.py b/api/schemas/schemas.py index 3c34bbfe8..b26f50cf5 100644 --- a/api/schemas/schemas.py +++ b/api/schemas/schemas.py @@ -404,6 +404,7 @@ class EventType(str, Enum): REQUEST_MOBILE = "requestMobile" ERROR_MOBILE = "errorMobile" SWIPE_MOBILE = "swipeMobile" + EVENT = "event" class PerformanceEventType(str, Enum): @@ -777,6 +778,15 @@ class SessionsSearchPayloadSchema(_TimedSchema, _PaginatedSchema): f["value"] = vals return values + @model_validator(mode="after") + def check_pa_event_filter(self): + for v in self.filters + self.events: + if v.type == EventType.EVENT: + assert v.operator in (SearchEventOperator.IS, MathOperator.EQUAL), \ + "operator must be {SearchEventOperator.IS} or {MathOperator.EQUAL} for EVENT type" + assert len(v.value) == 1, "value must have 1 single value for EVENT type" + return self + @model_validator(mode="after") def split_filters_events(self): n_filters = []