Skip to content

Commit 79f4df1

Browse files
committed
refactor: Removed default limit bug and added a new statistics endpoint for faster front-end viz rendering
1 parent 3c3e2ff commit 79f4df1

File tree

3 files changed

+141
-8
lines changed

3 files changed

+141
-8
lines changed

bom-bills.go

Lines changed: 126 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,6 @@ func parseAPIParameters(r *http.Request) (APIParameters, error) {
149149
EndYear: 1750,
150150
Parish: []int{},
151151
Sort: "year, week_no, canonical_name",
152-
Limit: 25, // Set a default limit
153152
}
154153

155154
// Log raw query parameters for debugging
@@ -298,16 +297,12 @@ func buildBillsQuery(params APIParameters) (string, error) {
298297
}
299298

300299
// Handle pagination
301-
queryPart := " LIMIT %d"
302300
if params.Page > 0 {
303-
// If using page-based pagination
304301
limit := 25
305302
offset := (params.Page - 1) * limit
306-
baseQuery += fmt.Sprintf(queryPart+" OFFSET %d", limit, offset)
307-
} else {
308-
// Always apply the limit (default or specified)
309-
baseQuery += fmt.Sprintf(queryPart, params.Limit)
310-
// Add offset if specified
303+
baseQuery += fmt.Sprintf(" LIMIT %d OFFSET %d", limit, offset)
304+
} else if params.Limit > 0 {
305+
baseQuery += fmt.Sprintf(" LIMIT %d", params.Limit)
311306
if params.Offset > 0 {
312307
baseQuery += fmt.Sprintf(" OFFSET %d", params.Offset)
313308
}
@@ -414,3 +409,126 @@ func (s *Server) TotalBillsHandler() http.HandlerFunc {
414409
fmt.Fprint(w, string(response))
415410
}
416411
}
412+
413+
// Statistics
414+
type YearlySummary struct {
415+
Year int `json:"year"`
416+
WeeksCompleted int `json:"weeksCompleted"`
417+
RowsCount int `json:"rowsCount"`
418+
TotalCount int `json:"totalCount"`
419+
}
420+
421+
type WeeklySummary struct {
422+
Year int `json:"year"`
423+
WeekNo int `json:"weekNo"`
424+
RowsCount int `json:"rowsCount"`
425+
}
426+
427+
func buildYearlyStatsQuery() string {
428+
return `
429+
WITH year_range AS (
430+
SELECT generate_series(1636, 1754) AS year
431+
),
432+
weekly_stats AS (
433+
SELECT
434+
b.year_id as year,
435+
COUNT(DISTINCT b.week_id) as weeks_completed,
436+
COUNT(*) as rows_count
437+
FROM bom.bill_of_mortality b
438+
WHERE b.bill_type = 'Weekly'
439+
GROUP BY b.year_id
440+
)
441+
SELECT
442+
yr.year,
443+
COALESCE(ws.weeks_completed, 0) as weeks_completed,
444+
COALESCE(ws.rows_count, 0) as rows_count,
445+
53 as total_count
446+
FROM year_range yr
447+
LEFT JOIN weekly_stats ws ON yr.year = ws.year
448+
ORDER BY yr.year;
449+
`
450+
}
451+
452+
func buildWeeklyStatsQuery() string {
453+
return `
454+
WITH year_week_range AS (
455+
SELECT
456+
y.year,
457+
w.number as week_no
458+
FROM generate_series(1636, 1754) y(year)
459+
CROSS JOIN generate_series(1, 53) w(number)
460+
),
461+
weekly_stats AS (
462+
SELECT
463+
b.year_id as year,
464+
w.week_no,
465+
COUNT(*) as rows_count
466+
FROM bom.bill_of_mortality b
467+
JOIN bom.week w ON w.joinid = b.week_id
468+
WHERE b.bill_type = 'Weekly'
469+
GROUP BY b.year_id, w.week_no
470+
)
471+
SELECT
472+
yr.year,
473+
yr.week_no,
474+
COALESCE(ws.rows_count, 0) as rows_count
475+
FROM year_week_range yr
476+
LEFT JOIN weekly_stats ws ON yr.year = ws.year AND yr.week_no = ws.week_no
477+
ORDER BY yr.year, yr.week_no;
478+
`
479+
}
480+
481+
func (s *Server) StatisticsHandler() http.HandlerFunc {
482+
return func(w http.ResponseWriter, r *http.Request) {
483+
statType := r.URL.Query().Get("type")
484+
485+
var query string
486+
switch statType {
487+
case "weekly":
488+
query = buildWeeklyStatsQuery()
489+
case "yearly":
490+
query = buildYearlyStatsQuery()
491+
default:
492+
http.Error(w, "Invalid type parameter. Must be 'weekly' or 'yearly'", http.StatusBadRequest)
493+
return
494+
}
495+
496+
rows, err := s.DB.Query(context.TODO(), query)
497+
if err != nil {
498+
http.Error(w, "Database error", http.StatusInternalServerError)
499+
return
500+
}
501+
defer rows.Close()
502+
503+
if statType == "weekly" {
504+
stats := []WeeklySummary{}
505+
for rows.Next() {
506+
var summary WeeklySummary
507+
err := rows.Scan(&summary.Year, &summary.WeekNo, &summary.RowsCount)
508+
if err != nil {
509+
http.Error(w, "Error processing results", http.StatusInternalServerError)
510+
return
511+
}
512+
stats = append(stats, summary)
513+
}
514+
w.Header().Set("Content-Type", "application/json")
515+
json.NewEncoder(w).Encode(stats)
516+
return
517+
}
518+
519+
stats := []YearlySummary{}
520+
for rows.Next() {
521+
var summary YearlySummary
522+
err := rows.Scan(&summary.Year, &summary.WeeksCompleted,
523+
&summary.RowsCount, &summary.TotalCount)
524+
if err != nil {
525+
http.Error(w, "Error processing results", http.StatusInternalServerError)
526+
return
527+
}
528+
stats = append(stats, summary)
529+
}
530+
531+
w.Header().Set("Content-Type", "application/json")
532+
json.NewEncoder(w).Encode(stats)
533+
}
534+
}

endpoints.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,20 @@ func (s *Server) EndpointsHandler() http.HandlerFunc {
140140
baseurl + "/bom/parishes",
141141
nil,
142142
},
143+
{
144+
"BOM: Completion Statistics",
145+
baseurl + "/bom/statistics",
146+
[]ExampleURL{
147+
{
148+
baseurl + "/bom/statistics?type=weekly",
149+
"Group completed bill transcriptions by week",
150+
},
151+
{
152+
baseurl + "/bom/statistics?type=yearly",
153+
"Group completed bill transcriptions by year",
154+
},
155+
},
156+
},
143157
{
144158
"BOM: Bills of Mortality",
145159
baseurl + "/bom/bills?start-year=1636&end-year=1754",

routes.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ func (s *Server) Routes() {
2020
s.Router.HandleFunc("/apb/verse-trend", s.APBVerseTrendHandler()).Methods("GET", "HEAD")
2121
s.Router.HandleFunc("/bom/parishes", s.ParishesHandler()).Methods("GET", "HEAD")
2222
s.Router.HandleFunc("/bom/totalbills", s.TotalBillsHandler()).Methods("GET", "HEAD")
23+
s.Router.HandleFunc("/bom/statistics", s.StatisticsHandler()).Methods("GET", "HEAD")
2324
s.Router.HandleFunc("/bom/bills", s.BillsHandler()).Methods("GET", "HEAD")
2425
s.Router.HandleFunc("/bom/christenings", s.ChristeningsHandler()).Methods("GET", "HEAD")
2526
s.Router.HandleFunc("/bom/causes", s.DeathCausesHandler()).Methods("GET", "HEAD")

0 commit comments

Comments
 (0)