feature(chalice): search sessions by x/y coordinates

feature(chalice): search heatmaps by x/y coordinates
This commit is contained in:
Taha Yassine Kraiem 2025-05-21 16:45:42 +02:00 committed by Kraiem Taha Yassine
parent f1e1d37d8e
commit 5b6e9ab7e0
4 changed files with 63 additions and 5 deletions

View file

@ -61,6 +61,9 @@ def get_heat_map_chart(project: schemas.ProjectContext, user_id, data: schemas.C
return None
data.series[0].filter.filters += data.series[0].filter.events
data.series[0].filter.events = []
print(">>>>>>>>>>>>>>>>>>>>>>>>><")
print(data.series[0].filter.model_dump())
print(">>>>>>>>>>>>>>>>>>>>>>>>><")
return heatmaps.search_short_session(project_id=project.project_id, user_id=user_id,
data=schemas.HeatMapSessionsSearch(
**data.series[0].filter.model_dump()),

View file

@ -1293,9 +1293,6 @@ def search_query_parts_ch(data: schemas.SessionsSearchPayloadSchema, error_statu
events_conditions.append({"type": event_where[-1]})
if is_not:
# event_where.append(json_condition(
# "sub", "$properties", _column, op, event.value, e_k
# ))
event_where.append(
sh.multi_conditions(
get_sub_condition(col_name=f"sub.`$properties`.{_column}",
@ -1317,7 +1314,33 @@ def search_query_parts_ch(data: schemas.SessionsSearchPayloadSchema, error_statu
event.value, value_key=e_k)
)
events_conditions[-1]["condition"] = event_where[-1]
elif event_type == schemas.EventType.CLICK_COORDINATES:
event_from = event_from % f"{MAIN_EVENTS_TABLE} AS main "
event_where.append(
f"main.`$event_name`='{exp_ch_helper.get_event_type(schemas.EventType.CLICK, platform=platform)}'")
events_conditions.append({"type": event_where[-1]})
if is_not:
event_where.append(
sh.coordinate_conditions(
condition_x=f"sub.`$properties`.normalized_x",
condition_y=f"sub.`$properties`.normalized_y",
values=event.value, value_key=e_k, is_not=True)
)
events_conditions_not.append(
{
"type": f"sub.`$event_name`='{exp_ch_helper.get_event_type(schemas.EventType.CLICK, platform=platform)}'"
}
)
events_conditions_not[-1]["condition"] = event_where[-1]
else:
event_where.append(
sh.coordinate_conditions(
condition_x=f"main.`$properties`.normalized_x",
condition_y=f"main.`$properties`.normalized_y",
values=event.value, value_key=e_k, is_not=True)
)
events_conditions[-1]["condition"] = event_where[-1]
else:
continue

View file

@ -44,7 +44,7 @@ def reverse_sql_operator(op):
return "=" if op == "!=" else "!=" if op == "=" else "ILIKE" if op == "NOT ILIKE" else "NOT ILIKE"
def multi_conditions(condition, values, value_key="value", is_not=False):
def multi_conditions(condition, values, value_key="value", is_not=False) -> str:
query = []
for i in range(len(values)):
k = f"{value_key}_{i}"
@ -79,3 +79,30 @@ def single_value(values):
if isinstance(v, Enum):
values[i] = v.value
return values
def coordinate_conditions(condition_x, condition_y, values, value_key="value", is_not=False):
query = []
if len(values) == 2:
# if 2 values are provided, it means x=v[0] and y=v[1]
for i in range(len(values)):
k = f"{value_key}_{i}"
if i == 0:
query.append(f"{condition_x}=%({k})s")
elif i == 1:
query.append(f"{condition_y}=%({k})s")
elif len(values) == 4:
# if 4 values are provided, it means v[0]<=x<=v[1] and v[2]<=y<=v[3]
for i in range(len(values)):
k = f"{value_key}_{i}"
if i == 0:
query.append(f"{condition_x}>=%({k})s")
elif i == 1:
query.append(f"{condition_x}<=%({k})s")
elif i == 2:
query.append(f"{condition_y}>=%({k})s")
elif i == 3:
query.append(f"{condition_y}<=%({k})s")
return "(" + (" AND " if is_not else " OR ").join(query) + ")"

View file

@ -407,6 +407,7 @@ class EventType(str, Enum):
SWIPE_MOBILE = "swipeMobile"
EVENT = "event"
INCIDENT = "incident"
CLICK_COORDINATES = "clickCoordinates"
class PerformanceEventType(str, Enum):
@ -660,6 +661,10 @@ class SessionSearchEventSchema(BaseModel):
elif self.type == EventType.GRAPHQL:
assert isinstance(self.filters, List) and len(self.filters) > 0, \
f"filters should be defined for {EventType.GRAPHQL}"
elif self.type == EventType.CLICK_COORDINATES:
assert isinstance(self.value, List) \
and (len(self.value) == 0 or len(self.value) == 2 or len(self.value) == 4), \
f"value should be [x,y] or [x1,x2,y1,y2] for {EventType.CLICK_COORDINATES}"
if isinstance(self.operator, ClickEventExtraOperator):
assert self.type == EventType.CLICK, \
@ -1521,7 +1526,7 @@ class MetricSearchSchema(_PaginatedSchema):
class _HeatMapSearchEventRaw(SessionSearchEventSchema):
type: Literal[EventType.LOCATION] = Field(...)
type: Literal[EventType.LOCATION, EventType.CLICK_COORDINATES] = Field(...)
class HeatMapSessionsSearch(SessionsSearchPayloadSchema):