예제 #1
0
파일: cohort.py 프로젝트: PostHog/posthog
def insert_cohort_actors_into_ch(cohort: Cohort, filter_data: Dict):
    insight_type = filter_data.get("insight")
    query_builder: ActorBaseQuery

    if insight_type == INSIGHT_TRENDS:
        filter = Filter(data=filter_data, team=cohort.team)
        entity = get_target_entity(filter)
        query_builder = ClickhouseTrendsActors(cohort.team, entity, filter)
    elif insight_type == INSIGHT_STICKINESS:
        stickiness_filter = StickinessFilter(data=filter_data,
                                             team=cohort.team)
        entity = get_target_entity(stickiness_filter)
        query_builder = ClickhouseStickinessActors(cohort.team, entity,
                                                   stickiness_filter)
    elif insight_type == INSIGHT_FUNNELS:
        funnel_filter = Filter(data=filter_data, team=cohort.team)
        if funnel_filter.correlation_person_entity:
            query_builder = FunnelCorrelationActors(filter=funnel_filter,
                                                    team=cohort.team)
        else:
            funnel_actor_class = get_funnel_actor_class(funnel_filter)
            query_builder = funnel_actor_class(filter=funnel_filter,
                                               team=cohort.team)
    elif insight_type == INSIGHT_PATHS:
        path_filter = PathFilter(data=filter_data, team=cohort.team)
        query_builder = ClickhousePathsActors(path_filter,
                                              cohort.team,
                                              funnel_filter=None)
    else:
        if settings.DEBUG:
            raise ValueError(
                f"Insight type: {insight_type} not supported for cohort creation"
            )
        else:
            capture_exception(
                Exception(
                    f"Insight type: {insight_type} not supported for cohort creation"
                ))

    if query_builder.is_aggregating_by_groups:
        if settings.DEBUG:
            raise ValueError(
                f"Query type: Group based queries are not supported for cohort creation"
            )
        else:
            capture_exception(
                Exception(
                    f"Query type: Group based queries are not supported for cohort creation"
                ))
    else:
        query, params = query_builder.actor_query(limit_actors=False)

    insert_actors_into_cohort_by_query(cohort, query, params)
예제 #2
0
    def people(self, request: Request, *args: Any, **kwargs: Any) -> Response:
        team = self.team
        filter = Filter(request=request)
        entity = get_target_entity(request)

        current_url = request.get_full_path()
        serialized_people = calculate_entity_people(team, entity, filter)

        current_url = request.get_full_path()
        next_url: Optional[str] = request.get_full_path()
        offset = filter.offset
        if len(serialized_people) > 100 and next_url:
            if "offset" in next_url:
                next_url = next_url[1:]
                next_url = next_url.replace("offset=" + str(offset), "offset=" + str(offset + 100))
            else:
                next_url = request.build_absolute_uri(
                    "{}{}offset={}".format(next_url, "&" if "?" in next_url else "?", offset + 100)
                )
        else:
            next_url = None
        return Response(
            {
                "results": [{"people": serialized_people[0:100], "count": len(serialized_people[0:99])}],
                "next": next_url,
                "previous": current_url[1:],
            }
        )
예제 #3
0
    def get_people(self,
                   request: request.Request) -> Union[Dict[str, Any], List]:
        team = self.team
        filter = Filter(request=request)
        entity = get_target_entity(request)

        events = filter_by_type(entity=entity, team=team, filter=filter)
        people = calculate_people(team=team, events=events, filter=filter)
        serialized_people = PersonSerializer(people,
                                             context={
                                                 "request": request
                                             },
                                             many=True).data

        current_url = request.get_full_path()
        next_url = paginated_result(serialized_people, request, filter.offset)

        return {
            "results": [{
                "people": serialized_people,
                "count": len(serialized_people)
            }],
            "next":
            next_url,
            "previous":
            current_url[1:],
        }
예제 #4
0
파일: person.py 프로젝트: copyit/posthog
    def stickiness(self, request: request.Request) -> response.Response:
        team = cast(User, request.user).team
        if not team:
            return response.Response(
                {
                    "message": "Could not retrieve team",
                    "detail": "Could not validate team associated with user"
                },
                status=400,
            )
        earliest_timestamp_func = lambda team_id: Event.objects.earliest_timestamp(
            team_id)
        filter = StickinessFilter(
            request=request,
            team=team,
            get_earliest_timestamp=earliest_timestamp_func)

        target_entity = get_target_entity(request)

        people = self.stickiness_class().people(target_entity, filter, team,
                                                request)
        next_url = paginated_result(people, request, filter.offset)
        return response.Response({
            "results": [{
                "people": people,
                "count": len(people)
            }],
            "next":
            next_url
        })
예제 #5
0
    def test_get_target_entity(self):
        request = lambda url: cast(Any, RequestFactory().get(url))
        filter = Filter(
            data={
                "entity_id": "$pageview",
                "entity_type": "events",
                "events": [{
                    "id": "$pageview",
                    "type": "events"
                }],
            })
        entity = get_target_entity(filter)

        assert entity.id == "$pageview"
        assert entity.type == "events"
        assert entity.math is None

        filter = Filter(
            data={
                "entity_id":
                "$pageview",
                "entity_type":
                "events",
                "entity_math":
                "unique_group",
                "events": [
                    {
                        "id": "$pageview",
                        "type": "events",
                        "math": "unique_group"
                    },
                    {
                        "id": "$pageview",
                        "type": "events"
                    },
                ],
            })
        entity = get_target_entity(filter)

        assert entity.id == "$pageview"
        assert entity.type == "events"
        assert entity.math == "unique_group"
예제 #6
0
    def people(self, request: request.Request, *args: Any,
               **kwargs: Any) -> Response:
        team = self.team
        filter = Filter(request=request, team=self.team)
        entity = get_target_entity(filter)

        actors, serialized_actors = ClickhouseTrendsActors(
            team, entity, filter).get_actors()

        current_url = request.get_full_path()
        next_url: Optional[str] = request.get_full_path()
        offset = filter.offset
        if len(actors) > 100 and next_url:
            if "offset" in next_url:
                next_url = next_url[1:]
                next_url = next_url.replace("offset=" + str(offset),
                                            "offset=" + str(offset + 100))
            else:
                next_url = request.build_absolute_uri("{}{}offset={}".format(
                    next_url, "&" if "?" in next_url else "?", offset + 100))
        else:
            next_url = None

        if request.accepted_renderer.format == "csv":
            csvrenderers.CSVRenderer.header = [
                "Distinct ID", "Internal ID", "Email", "Name", "Properties"
            ]
            content = [{
                "Name":
                get_person_name(person),
                "Distinct ID":
                person.distinct_ids[0] if person.distinct_ids else "",
                "Internal ID":
                str(person.uuid),
                "Email":
                person.properties.get("email"),
                "Properties":
                person.properties,
            } for person in actors if isinstance(person, Person)]
            return Response(content)

        return Response({
            "results": [{
                "people": serialized_actors[0:100],
                "count": len(serialized_actors[0:100])
            }],
            "next":
            next_url,
            "previous":
            current_url[1:],
        })
예제 #7
0
    def stickiness(self, request: request.Request) -> response.Response:
        team = cast(User, request.user).team
        if not team:
            return response.Response(
                {"message": "Could not retrieve team", "detail": "Could not validate team associated with user"},
                status=400,
            )
        filter = StickinessFilter(request=request, team=team, get_earliest_timestamp=get_earliest_timestamp)
        if not filter.limit:
            filter = filter.with_data({LIMIT: 100})

        target_entity = get_target_entity(filter)

        people = self.stickiness_class().people(target_entity, filter, team, request)
        next_url = paginated_result(people, request, filter.offset)
        return response.Response({"results": [{"people": people, "count": len(people)}], "next": next_url})
예제 #8
0
    def people(self, request: Request, *args: Any,
               **kwargs: Any) -> Response:  # type: ignore
        team = self.team
        filter = Filter(request=request, team=self.team)
        entity = get_target_entity(request)

        current_url = request.get_full_path()
        serialized_people = TrendsPersonQuery(team, entity,
                                              filter).get_people()

        current_url = request.get_full_path()
        next_url: Optional[str] = request.get_full_path()
        offset = filter.offset
        if len(serialized_people) > 100 and next_url:
            if "offset" in next_url:
                next_url = next_url[1:]
                next_url = next_url.replace("offset=" + str(offset),
                                            "offset=" + str(offset + 100))
            else:
                next_url = request.build_absolute_uri("{}{}offset={}".format(
                    next_url, "&" if "?" in next_url else "?", offset + 100))
        else:
            next_url = None

        if request.accepted_renderer.format == "csv":
            csvrenderers.CSVRenderer.header = [
                "Distinct ID", "Internal ID", "Email", "Name", "Properties"
            ]
            content = [{
                "Name": person.get("properties", {}).get("name"),
                "Distinct ID": person.get("distinct_ids", [""])[0],
                "Internal ID": person.get("id"),
                "Email": person.get("properties", {}).get("email"),
                "Properties": person.get("properties", {}),
            } for person in serialized_people]
            return Response(content)

        return Response({
            "results": [{
                "people": serialized_people[0:100],
                "count": len(serialized_people[0:100])
            }],
            "next":
            next_url,
            "previous":
            current_url[1:],
        })
예제 #9
0
파일: cohort.py 프로젝트: younghai/posthog
 def _handle_static(self, cohort: Cohort, request: Request):
     if request.FILES.get("csv"):
         self._calculate_static_by_csv(request.FILES["csv"], cohort)
     else:
         try:
             filter = Filter(request=request)
             team = request.user.team
             target_entity = get_target_entity(request)
             if filter.shown_as == TRENDS_STICKINESS:
                 stickiness_filter = StickinessFilter(
                     request=request, team=team, get_earliest_timestamp=self.earliest_timestamp_func
                 )
                 self._handle_stickiness_people(target_entity, cohort, stickiness_filter)
             else:
                 self._handle_trend_people(target_entity, cohort, filter)
         except Exception as e:
             capture_exception(e)
             raise ValueError("This cohort has no conditions")
예제 #10
0
    def get_people(self,
                   request: request.Request) -> Union[Dict[str, Any], List]:
        team = self.team
        filter = Filter(request=request)
        entity = get_target_entity(request)

        events = filter_by_type(entity=entity, team=team, filter=filter)
        people = calculate_people(team=team,
                                  events=events,
                                  filter=filter,
                                  request=request)
        serialized_people = PersonSerializer(people,
                                             context={
                                                 "request": request
                                             },
                                             many=True).data

        current_url = request.get_full_path()
        next_url = paginated_result(serialized_people, request, filter.offset)

        if request.accepted_renderer.format == "csv":
            csvrenderers.CSVRenderer.header = [
                "Distinct ID", "Internal ID", "Email", "Name", "Properties"
            ]
            content = [{
                "Name": person.get("properties", {}).get("name"),
                "Distinct ID": person.get("distinct_ids", [""])[0],
                "Internal ID": person["uuid"],
                "Email": person.get("properties", {}).get("email"),
                "Properties": person.get("properties", {}),
            } for person in serialized_people]
            return content

        return {
            "results": [{
                "people": serialized_people,
                "count": len(serialized_people)
            }],
            "next":
            next_url,
            "previous":
            current_url[1:],
        }
예제 #11
0
    def people(self, request: Request, *args: Any, **kwargs: Any) -> Response:
        team = self.team
        filter = Filter(request=request)
        entity = get_target_entity(request)

        # adhoc date handling. parsed differently with django orm
        date_from = filter.date_from or timezone.now()
        data = {}
        if filter.interval == "month":
            data.update(
                {"date_to": (date_from + relativedelta(months=1) - timedelta(days=1)).strftime("%Y-%m-%d %H:%M:%S")}
            )
        elif filter.interval == "week":
            data.update({"date_to": (date_from + relativedelta(weeks=1)).strftime("%Y-%m-%d %H:%M:%S")})
        elif filter.interval == "hour":
            data.update({"date_to": date_from + timedelta(hours=1)})
        elif filter.interval == "minute":
            data.update({"date_to": date_from + timedelta(minutes=1)})
        filter = Filter(data={**filter._data, **data})

        current_url = request.get_full_path()
        serialized_people = self._calculate_entity_people(team, entity, filter)

        current_url = request.get_full_path()
        next_url: Optional[str] = request.get_full_path()
        offset = filter.offset
        if len(serialized_people) > 100 and next_url:
            if "offset" in next_url:
                next_url = next_url[1:]
                next_url = next_url.replace("offset=" + str(offset), "offset=" + str(offset + 100))
            else:
                next_url = request.build_absolute_uri(
                    "{}{}offset={}".format(next_url, "&" if "?" in next_url else "?", offset + 100)
                )
        else:
            next_url = None
        return Response(
            {
                "results": [{"people": serialized_people[0:100], "count": len(serialized_people[0:99])}],
                "next": next_url,
                "previous": current_url[1:],
            }
        )
예제 #12
0
    def get_people(self,
                   request: request.Request) -> Union[Dict[str, Any], List]:
        team = self.team
        filter = Filter(request=request)
        offset = int(request.GET.get("offset", 0))

        def _calculate_people(events: QuerySet, offset: int):
            events = events.values("person_id").distinct()

            if request.GET.get(
                    "breakdown_type"
            ) == "cohort" and request.GET.get("breakdown_value") != "all":
                events = events.filter(
                    Exists(
                        CohortPeople.objects.filter(
                            cohort_id=int(request.GET["breakdown_value"]),
                            person_id=OuterRef("person_id"),
                        ).only("id")))
            if request.GET.get("breakdown_type") == "person":
                events = events.filter(
                    Exists(
                        Person.objects.filter(
                            **{
                                "id":
                                OuterRef("person_id"),
                                "team_id":
                                self.team.pk,
                                "properties__{}".format(request.GET["breakdown"]):
                                request.GET["breakdown_value"],
                            }).only("id")))

            people = Person.objects.filter(
                team=team,
                id__in=[p["person_id"] for p in events[offset:offset + 100]])

            people = people.prefetch_related(
                Prefetch("persondistinctid_set", to_attr="distinct_ids_cache"))

            return PersonSerializer(people,
                                    context={
                                        "request": request
                                    },
                                    many=True).data

        filtered_events: QuerySet = QuerySet()
        if request.GET.get("session"):
            filtered_events = (Event.objects.filter(team=team).filter(
                base.filter_events(team.pk, filter)).add_person_id(team.pk))
        else:
            entity = get_target_entity(request)

            if entity.type == TREND_FILTER_TYPE_EVENTS:
                filtered_events = base.process_entity_for_events(
                    entity, team_id=team.pk, order_by=None).filter(
                        base.filter_events(team.pk, filter, entity))
            elif entity.type == TREND_FILTER_TYPE_ACTIONS:
                actions = super().get_queryset()
                actions = actions.filter(deleted=False)
                try:
                    action = actions.get(pk=entity.id)
                except Action.DoesNotExist:
                    return []
                filtered_events = base.process_entity_for_events(
                    entity, team_id=team.pk, order_by=None).filter(
                        base.filter_events(team.pk, filter, entity))

        people = _calculate_people(events=filtered_events, offset=offset)

        current_url = request.get_full_path()
        next_url = paginated_result(people, request, offset)

        return {
            "results": [{
                "people": people,
                "count": len(people)
            }],
            "next": next_url,
            "previous": current_url[1:]
        }