0
0
mirror of https://github.com/PostHog/posthog.git synced 2024-11-30 19:41:46 +01:00
posthog/ee/clickhouse/models/property.py
Eric Duong 58ecefd9c8
Add per entity filtering (#1838)
* add per entity filtering to breakdown and regular queries on trends page

* add test for per entity filtering on trends
2020-10-13 08:17:24 -04:00

71 lines
2.4 KiB
Python

from typing import Dict, List, Optional, Tuple
from ee.clickhouse.client import sync_execute
from ee.clickhouse.models.cohort import format_cohort_table_name
from ee.clickhouse.sql.cohort import COHORT_DISTINCT_ID_FILTER_SQL
from ee.clickhouse.sql.events import EVENT_PROP_CLAUSE, SELECT_PROP_VALUES_SQL, SELECT_PROP_VALUES_SQL_WITH_FILTER
from posthog.models.cohort import Cohort
from posthog.models.property import Property
from posthog.models.team import Team
def parse_prop_clauses(key: str, filters: List[Property], team: Team, prepend: str = "") -> Tuple[str, Dict]:
final = ""
params = {}
for idx, prop in enumerate(filters):
if prop.type == "cohort":
cohort = Cohort.objects.get(pk=prop.value)
clause = COHORT_DISTINCT_ID_FILTER_SQL.format(table_name=format_cohort_table_name(cohort))
final += "{cond} ({clause}) ".format(cond="AND distinct_id IN", clause=clause)
else:
filter = "(ep.key = %(k{prepend}_{idx})s) AND (ep.value {operator} %(v{prepend}_{idx})s)".format(
idx=idx, operator=get_operator(prop.operator), prepend=prepend
)
clause = EVENT_PROP_CLAUSE.format(team_id=team.pk, filters=filter)
final += "{cond} ({clause}) ".format(cond="AND {key} IN".format(key=key), clause=clause)
params.update(
{"k{}_{}".format(prepend, idx): prop.key, "v{}_{}".format(prepend, idx): _pad_value(prop.value)}
)
return final, params
def _pad_value(val: str):
if not val.startswith('"'):
val = '"' + val
if not val.endswith('"'):
val = val + '"'
return val
# TODO: handle all operators
def get_operator(operator: Optional[str]):
if operator == "is_not":
return "!="
elif operator == "icontains":
return "LIKE"
elif operator == "not_icontains":
return "NOT LIKE"
elif operator == "regex":
return "="
elif operator == "not_regex":
return "="
elif operator == "gt":
return ">"
elif operator == "lt":
return "<"
else:
return "="
def get_property_values_for_key(key: str, team: Team, value: Optional[str] = None):
if value:
return sync_execute(
SELECT_PROP_VALUES_SQL_WITH_FILTER, {"team_id": team.pk, "key": key, "value": "%{}%".format(value)}
)
return sync_execute(SELECT_PROP_VALUES_SQL, {"team_id": team.pk, "key": key})