need rework

This commit is contained in:
Pavel 2024-06-14 21:06:01 +03:00
parent 4c6649bd30
commit fac78b1256

@ -29,8 +29,10 @@ func NewClickStatistic(ctx context.Context, deps DepsClick) (*StatisticClick, er
}
// todo toanaliz for keydevice,keydevicetype,keybrowser,
// todo получается пока какая то фигня
func (s *StatisticClick) checkMW(ctx context.Context) error {
// в мат вью получаем последний ссесионный координат, то есть тот момент на котором сессия в квизе завершилась
// не зависит какой это тип вопроса, страт, обычный, резулт, получаем всегда последний у сессии
// он определят конечное положение пользователя в опросе
query := `
CREATE MATERIALIZED VIEW IF NOT EXISTS mv_last_answers_events
ENGINE = MergeTree()
@ -61,57 +63,82 @@ type Statistic struct {
type PipeLineStatsResp [][]Statistic
type FunnelData struct {
QuestionID int64
Count int64
Session string
QuestionIDs []int64
}
func (s *StatisticClick) funnelData(ctx context.Context, quizID int64, from uint64, to uint64) ([]FunnelData, error) {
query := `
SELECT ctxquestionid, uniqExact(ctxsession) AS count
FROM mv_last_answers_events
WHERE ctxquizid = ? AND event_time BETWEEN ? AND ?
GROUP BY ctxquestionid
`
rows, err := s.conn.QueryContext(ctx, query, quizID, from, to)
// получили все уникальные сессии из мат вью
sessionQuery := `
SELECT DISTINCT ctxsession
FROM mv_last_answers_events
WHERE ctxquizid = ? AND event_time BETWEEN ? AND ?
`
sessionRows, err := s.conn.QueryContext(ctx, sessionQuery, quizID, from, to)
if err != nil {
return nil, err
}
defer rows.Close()
var data []FunnelData
for rows.Next() {
var questionID int64
var count int64
defer sessionRows.Close()
err := rows.Scan(&questionID, &count)
var funnelData []FunnelData
for sessionRows.Next() {
var ctxsession string
err := sessionRows.Scan(&ctxsession)
if err != nil {
return nil, err
}
// получаем вопросы уникальные, последние в рамках сессии
questionQuery := `
SELECT DISTINCT ctxquestionid
FROM statistics WHERE ctxsession = ? ORDER BY event_time DESC;
`
questionRows, err := s.conn.QueryContext(ctx, questionQuery, ctxsession)
if err != nil {
return nil, err
}
defer questionRows.Close()
data = append(data, FunnelData{
QuestionID: questionID,
Count: count,
var questions []int64
for questionRows.Next() {
var ctxquestionid int64
err := questionRows.Scan(&ctxquestionid)
if err != nil {
return nil, err
}
questions = append(questions, ctxquestionid)
}
fmt.Println("questions", questions)
if err := questionRows.Err(); err != nil {
return nil, err
}
funnelData = append(funnelData, FunnelData{
Session: ctxsession,
QuestionIDs: questions,
})
}
if err := rows.Err(); err != nil {
if err := sessionRows.Err(); err != nil {
return nil, err
}
return data, nil
return funnelData, nil
}
// выборка вопросов с одной воронкой
// todo еще раз понять подумать осознать как подписывать воронку сейчас если массив соддержит 1 элемент это старт ответ
func (s *StatisticClick) getOneFunnelQuestions(ctx context.Context, quizID int64, from uint64, to uint64) ([]int64, error) {
var result []int64
questionCounts, err := s.funnelData(ctx, quizID, from, to)
funnelData, err := s.funnelData(ctx, quizID, from, to)
if err != nil {
return nil, err
}
for _, qc := range questionCounts {
if qc.Count == 1 {
result = append(result, qc.QuestionID)
for _, fd := range funnelData {
if len(fd.QuestionIDs) == 1 {
result = append(result, fd.QuestionIDs...)
}
}
@ -119,63 +146,60 @@ func (s *StatisticClick) getOneFunnelQuestions(ctx context.Context, quizID int64
}
func (s *StatisticClick) GetPipelinesStatistics(ctx context.Context, quizID int64, from uint64, to uint64) (PipeLineStatsResp, error) {
// тут нужно подписать все вопросы, которые принадлежат окончанию сессии, то есть массив ответов до окончания сессии
// это делается для каждой из сессии которая имеется в мат вью, это отношение к результату которого достиг респондент
// для того чтобы получить индентификатор воронки, то есть тот который последний этап прохождения был, то на чем все закончилось
// нужно из всех подписанных которые подписываются массивом и нужно выбрать из всех подписанных ответов на вопросы, выбрать те
// которые имеет всего один элемент в списке, то есть достижение никакого другого вопроса или результата не проходило через
// этот ответа кроме попытки достигнуть этотго оттвета или результата, это и являются конечные точки прохождения вопросов и от них считаются воронки и являются индентификаторами воронки
// именно те которые с массивом с 1 элементом
// нужно вернуть в каждом списке пару, id вопроса и количество ответов на этот вопрос, count - уникальные сессии которые прошли через этот вопрос
var pipelines PipeLineStatsResp
idS, err := s.getOneFunnelQuestions(ctx, quizID, from, to)
if err != nil {
return nil, err
}
query := `
SELECT
ctxsession,ctxquestionid,count(*) as session_count
FROM mv_last_answers_events WHERE ctxquizid = ? AND ctxquestionid = ? AND event_time BETWEEN ? AND ?
GROUP BY ctxsession, ctxquestionid ORDER BY ctxsession, ctxquestionid
`
for _, questionID := range idS {
query := `
SELECT ctxquestionid, COUNT(DISTINCT ctxsession) AS session_count
FROM mv_last_answers_events
WHERE ctxquizid = ? AND ctxquestionid = ? AND event_time BETWEEN ? AND ?
GROUP BY ctxquestionid
`
for _, quiestionID := range idS {
rows, err := s.conn.QueryContext(ctx, query, quizID, quiestionID, from, to)
rows, err := s.conn.QueryContext(ctx, query, quizID, questionID, from, to)
if err != nil {
return nil, err
}
defer rows.Close()
var currentPipeline []Statistic
var lastSession string
for rows.Next() {
var session string
var questionID int64
var id int64
var count int64
err := rows.Scan(&session, &questionID, &count)
err := rows.Scan(&id, &count)
if err != nil {
return nil, err
}
// новая сессия - новая воронка
if session != lastSession {
if lastSession != "" {
pipelines = append(pipelines, currentPipeline)
}
currentPipeline = []Statistic{}
}
// текущая статистика в текущую воронку
currentPipeline = append(currentPipeline, Statistic{
QuestionID: id,
Count: count,
QuestionID: questionID,
})
lastSession = session
}
// последня воронка если есть то добавляем
if len(currentPipeline) > 0 {
pipelines = append(pipelines, currentPipeline)
}
if err := rows.Err(); err != nil {
return nil, err
}
if len(currentPipeline) > 0 {
pipelines = append(pipelines, currentPipeline)
}
}
return pipelines, nil