feat(chalice): search sessions by global properties
feat(chalice): search sessions by negative global properties
This commit is contained in:
parent
51b838a2b4
commit
644a7b68b0
2 changed files with 44 additions and 2 deletions
|
|
@ -410,7 +410,8 @@ def search_query_parts_ch(data: schemas.SessionsSearchPayloadSchema, error_statu
|
||||||
],
|
],
|
||||||
"operator": "is"
|
"operator": "is"
|
||||||
}))
|
}))
|
||||||
|
global_properties = []
|
||||||
|
global_properties_negative = []
|
||||||
if len(data.filters) > 0:
|
if len(data.filters) > 0:
|
||||||
meta_keys = None
|
meta_keys = None
|
||||||
# to reduce include a sub-query of sessions inside events query, in order to reduce the selected data
|
# to reduce include a sub-query of sessions inside events query, in order to reduce the selected data
|
||||||
|
|
@ -429,6 +430,23 @@ def search_query_parts_ch(data: schemas.SessionsSearchPayloadSchema, error_statu
|
||||||
is_not = False
|
is_not = False
|
||||||
if sh.is_negation_operator(f.operator):
|
if sh.is_negation_operator(f.operator):
|
||||||
is_not = True
|
is_not = True
|
||||||
|
if not f.is_predefined:
|
||||||
|
cast = get_col_cast(data_type=f.data_type, value=f.value)
|
||||||
|
if is_any:
|
||||||
|
global_properties.append(f'isNotNull(e.properties.`{f.type}`)')
|
||||||
|
else:
|
||||||
|
if is_not:
|
||||||
|
op = sh.reverse_sql_operator(op)
|
||||||
|
global_properties_negative.append(sh.multi_conditions(get_sub_condition(
|
||||||
|
col_name=f"accurateCastOrNull(e.properties.`{f.type}`,'{cast}')",
|
||||||
|
val_name=f_k, operator=op), f.value, is_not=False, value_key=f_k))
|
||||||
|
else:
|
||||||
|
global_properties.append(sh.multi_conditions(get_sub_condition(
|
||||||
|
col_name=f"accurateCastOrNull(e.properties.`{f.type}`,'{cast}')",
|
||||||
|
val_name=f_k, operator=f.operator), f.value, is_not=False, value_key=f_k))
|
||||||
|
|
||||||
|
continue
|
||||||
|
|
||||||
if filter_type == schemas.FilterType.USER_BROWSER:
|
if filter_type == schemas.FilterType.USER_BROWSER:
|
||||||
if is_any:
|
if is_any:
|
||||||
extra_constraints.append('isNotNull(s.user_browser)')
|
extra_constraints.append('isNotNull(s.user_browser)')
|
||||||
|
|
@ -658,6 +676,11 @@ def search_query_parts_ch(data: schemas.SessionsSearchPayloadSchema, error_statu
|
||||||
events_conditions_where.append(f"""main.session_id IN (SELECT s.session_id
|
events_conditions_where.append(f"""main.session_id IN (SELECT s.session_id
|
||||||
FROM {MAIN_SESSIONS_TABLE} AS s
|
FROM {MAIN_SESSIONS_TABLE} AS s
|
||||||
WHERE {" AND ".join(extra_constraints)})""")
|
WHERE {" AND ".join(extra_constraints)})""")
|
||||||
|
|
||||||
|
if len(global_properties) > 0:
|
||||||
|
global_properties += ["e.project_id=%(project_id)s",
|
||||||
|
"e.created_at >= toDateTime(%(startDate)s/1000)",
|
||||||
|
"e.created_at <= toDateTime(%(endDate)s/1000)"]
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
events_extra_join = ""
|
events_extra_join = ""
|
||||||
if len(data.events) > 0:
|
if len(data.events) > 0:
|
||||||
|
|
@ -1612,6 +1635,18 @@ def search_query_parts_ch(data: schemas.SessionsSearchPayloadSchema, error_statu
|
||||||
ORDER BY _timestamp DESC) AS s ON(s.session_id=f.session_id)"""
|
ORDER BY _timestamp DESC) AS s ON(s.session_id=f.session_id)"""
|
||||||
else:
|
else:
|
||||||
deduplication_keys = ["session_id"] + extra_deduplication
|
deduplication_keys = ["session_id"] + extra_deduplication
|
||||||
|
if len(global_properties) > 0:
|
||||||
|
extra_join += f""" INNER JOIN (SELECT DISTINCT session_id
|
||||||
|
FROM {MAIN_EVENTS_TABLE} AS e
|
||||||
|
WHERE {" AND ".join(global_properties)}) AS global_filters USING(session_id)"""
|
||||||
|
if len(global_properties_negative) > 0:
|
||||||
|
extra_join += f""" LEFT JOIN (SELECT DISTINCT session_id
|
||||||
|
FROM {MAIN_EVENTS_TABLE} AS e
|
||||||
|
WHERE project_id=%(project_id)s
|
||||||
|
AND created_at >= toDateTime(%(startDate)s/1000)
|
||||||
|
AND created_at <= toDateTime(%(endDate)s/1000)
|
||||||
|
AND ({" OR ".join(global_properties_negative)})) AS negative_global_filters USING(session_id)"""
|
||||||
|
extra_constraints.append("isNull(negative_global_filters.session_id)")
|
||||||
extra_join = f"""(SELECT *
|
extra_join = f"""(SELECT *
|
||||||
FROM {MAIN_SESSIONS_TABLE} AS s {extra_join} {extra_event}
|
FROM {MAIN_SESSIONS_TABLE} AS s {extra_join} {extra_event}
|
||||||
WHERE {" AND ".join(extra_constraints)}
|
WHERE {" AND ".join(extra_constraints)}
|
||||||
|
|
|
||||||
|
|
@ -682,13 +682,20 @@ class SessionSearchEventSchema(BaseModel):
|
||||||
class SessionSearchFilterSchema(BaseModel):
|
class SessionSearchFilterSchema(BaseModel):
|
||||||
is_event: Literal[False] = False
|
is_event: Literal[False] = False
|
||||||
value: List[Union[IssueType, PlatformType, int, str]] = Field(default_factory=list)
|
value: List[Union[IssueType, PlatformType, int, str]] = Field(default_factory=list)
|
||||||
type: FilterType = Field(...)
|
type: Union[FilterType, str] = Field(...)
|
||||||
operator: Union[SearchEventOperator, MathOperator] = Field(...)
|
operator: Union[SearchEventOperator, MathOperator] = Field(...)
|
||||||
source: Optional[Union[ErrorSource, str]] = Field(default=None)
|
source: Optional[Union[ErrorSource, str]] = Field(default=None)
|
||||||
|
# used for global-properties
|
||||||
|
data_type: Optional[PropertyType] = Field(default=PropertyType.STRING.value)
|
||||||
|
|
||||||
_remove_duplicate_values = field_validator('value', mode='before')(remove_duplicate_values)
|
_remove_duplicate_values = field_validator('value', mode='before')(remove_duplicate_values)
|
||||||
_single_to_list_values = field_validator('value', mode='before')(single_to_list)
|
_single_to_list_values = field_validator('value', mode='before')(single_to_list)
|
||||||
|
|
||||||
|
@computed_field
|
||||||
|
@property
|
||||||
|
def is_predefined(self) -> bool:
|
||||||
|
return FilterType.has_value(self.type)
|
||||||
|
|
||||||
@model_validator(mode="before")
|
@model_validator(mode="before")
|
||||||
@classmethod
|
@classmethod
|
||||||
def _transform_data(cls, values):
|
def _transform_data(cls, values):
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue