feat(analyticsApi): added better api for page counts
Build and Push Docker image / build-and-push (push) Successful in 2m10s
Details
Build and Push Docker image / build-and-push (push) Successful in 2m10s
Details
This commit is contained in:
parent
23b0e7cf84
commit
fe232533c3
|
@ -14,44 +14,45 @@ import (
|
|||
|
||||
// initPageViewCount
|
||||
//
|
||||
// This endpoint is used to retrieve page view counts for each unique path.
|
||||
// This endpoint is used to retrieve paginated page view counts for each unique path.
|
||||
// It adds the following endpoint to the app:
|
||||
// GET /api/analytics/pageViewCount
|
||||
//
|
||||
// The endpoint expects the following query parameters:
|
||||
// Query parameters:
|
||||
//
|
||||
// ?startDate=ISO 8601 formatted date (optional)
|
||||
// ?page=<page number>
|
||||
// ?perPage=<results per page>
|
||||
// ?sort=<ASC|DESC> (default is ASC)
|
||||
// ?startDate=ISO 8601 formatted date (optional)
|
||||
// ?page=<page number>
|
||||
// ?perPage=<results per page>
|
||||
// ?sort=<ASC|DESC> (default is ASC)
|
||||
//
|
||||
// - `startDate`: An optional start date in ISO 8601 format (e.g., "2024-11-12T15:04:05Z").
|
||||
// If provided, the global count reflects views from this date onward.
|
||||
// If not provided, the global count includes all views.
|
||||
// - `page`: Page number for pagination (default is 1).
|
||||
// - `perPage`: Number of results per page for pagination (default is 10).
|
||||
// - `sort`: Sorting order, either `ASC` or `DESC` for ascending or descending order.
|
||||
// - `startDate`: Optional start date in ISO 8601 format (e.g., "2024-11-12T15:04:05Z").
|
||||
// - `page`: Page number for pagination (default is 1).
|
||||
// - `perPage`: Number of results per page (default is 10).
|
||||
// - `sort`: Sorting order, either `ASC` or `DESC` (default is ASC).
|
||||
//
|
||||
// Response format:
|
||||
// [
|
||||
//
|
||||
// {
|
||||
// "id": <unique row id>,
|
||||
// "data": "<path>",
|
||||
// "count": <total view count since startDate>,
|
||||
// "last_30_days_data": [
|
||||
// "page": <current page number>,
|
||||
// "perPage": <results per page>,
|
||||
// "totalItems": <total number of items matching the filter>,
|
||||
// "totalPages": <total number of pages>,
|
||||
// "items": [
|
||||
// {
|
||||
// "date": "YYYY-MM-DDTHH:MM:SSZ",
|
||||
// "count": <daily count>
|
||||
// "id": <unique row id>,
|
||||
// "path": "<path>",
|
||||
// "count": <total view count since startDate>,
|
||||
// "last_30_days_data": [
|
||||
// {
|
||||
// "date": "YYYY-MM-DDTHH:MM:SSZ",
|
||||
// "count": <daily count>
|
||||
// },
|
||||
// ...
|
||||
// ]
|
||||
// },
|
||||
// ...
|
||||
// ]
|
||||
// },
|
||||
// ...
|
||||
//
|
||||
// ]
|
||||
//
|
||||
// `last_30_days_data` always provides daily counts for the most recent 30 days regardless of the `startDate` parameter.
|
||||
// }
|
||||
func initPageViewCount(app *pocketbase.PocketBase, e *core.ServeEvent) {
|
||||
|
||||
e.Router.GET("/api/analytics/pageViewCount", func(c echo.Context) error {
|
||||
|
@ -72,7 +73,7 @@ func initPageViewCount(app *pocketbase.PocketBase, e *core.ServeEvent) {
|
|||
}
|
||||
}
|
||||
|
||||
// Get pagination and sorting parameters
|
||||
// Pagination and sorting parameters
|
||||
page, _ := strconv.Atoi(c.QueryParam("page"))
|
||||
if page < 1 {
|
||||
page = 1
|
||||
|
@ -90,21 +91,45 @@ func initPageViewCount(app *pocketbase.PocketBase, e *core.ServeEvent) {
|
|||
|
||||
offset := (page - 1) * perPage
|
||||
|
||||
type PageViewData struct {
|
||||
ID int `json:"id"`
|
||||
Data string `json:"data"`
|
||||
Count int `json:"count"`
|
||||
Last30DaysData interface{} `json:"last_30_days_data"`
|
||||
// Fetch total items for pagination
|
||||
var totalItems int
|
||||
err = app.Dao().DB().
|
||||
NewQuery(`
|
||||
SELECT COUNT(DISTINCT path) as total
|
||||
FROM analyticsPageViews
|
||||
WHERE created >= {:startDate}
|
||||
`).
|
||||
Bind(dbx.Params{
|
||||
"startDate": startDate,
|
||||
}).
|
||||
Row(&totalItems)
|
||||
|
||||
if err != nil {
|
||||
return apis.NewApiError(500, "Failed to count total items", err)
|
||||
}
|
||||
|
||||
var result []PageViewData
|
||||
totalPages := (totalItems + perPage - 1) / perPage // Calculate total pages
|
||||
|
||||
// Execute the query with nested JSON aggregation, pagination, and sorting
|
||||
// Define the structure for items
|
||||
type Last30DaysData struct {
|
||||
Date string `json:"date"`
|
||||
Count int `json:"count"`
|
||||
}
|
||||
|
||||
type Item struct {
|
||||
ID int `json:"id"`
|
||||
Path string `json:"path"`
|
||||
Count int `json:"count"`
|
||||
Last30DaysData []Last30DaysData `json:"last_30_days_data"`
|
||||
}
|
||||
|
||||
// Query paginated items
|
||||
var items []Item
|
||||
err = app.Dao().DB().
|
||||
NewQuery(`
|
||||
SELECT
|
||||
(ROW_NUMBER() OVER()) AS id,
|
||||
view.path AS data,
|
||||
view.path AS path,
|
||||
(
|
||||
SELECT COUNT(id)
|
||||
FROM analyticsPageViews
|
||||
|
@ -133,7 +158,7 @@ func initPageViewCount(app *pocketbase.PocketBase, e *core.ServeEvent) {
|
|||
GROUP BY
|
||||
view.path
|
||||
ORDER BY
|
||||
data ` + sort + `
|
||||
path ` + sort + `
|
||||
LIMIT {:perPage} OFFSET {:offset}
|
||||
`).
|
||||
Bind(dbx.Params{
|
||||
|
@ -141,14 +166,23 @@ func initPageViewCount(app *pocketbase.PocketBase, e *core.ServeEvent) {
|
|||
"perPage": perPage,
|
||||
"offset": offset,
|
||||
}).
|
||||
All(&result)
|
||||
All(&items)
|
||||
|
||||
if err != nil {
|
||||
return apis.NewApiError(500, "Failed to query page view data", err)
|
||||
}
|
||||
|
||||
// Final response structure
|
||||
response := map[string]interface{}{
|
||||
"page": page,
|
||||
"perPage": perPage,
|
||||
"totalItems": totalItems,
|
||||
"totalPages": totalPages,
|
||||
"items": items,
|
||||
}
|
||||
|
||||
// Return the final JSON response
|
||||
return c.JSON(200, result)
|
||||
return c.JSON(200, response)
|
||||
}, apis.ActivityLogger(app))
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue