234 lines
8.1 KiB
Go
234 lines
8.1 KiB
Go
package repository
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
|
|
"go.mongodb.org/mongo-driver/v2/bson"
|
|
"go.mongodb.org/mongo-driver/v2/mongo"
|
|
"go.mongodb.org/mongo-driver/v2/mongo/options"
|
|
)
|
|
|
|
type TranscriptionRepo struct {
|
|
col *mongo.Collection
|
|
}
|
|
|
|
func NewTranscriptionRepo(db *MongoDB) *TranscriptionRepo {
|
|
return &TranscriptionRepo{col: db.Collection("transcriptions")}
|
|
}
|
|
|
|
type ContentBlockDoc struct {
|
|
Text string `bson:"text" json:"text"`
|
|
Format string `bson:"format" json:"format"`
|
|
Alignment string `bson:"alignment" json:"alignment"`
|
|
Speaker *string `bson:"speaker,omitempty" json:"speaker,omitempty"`
|
|
}
|
|
|
|
type TranscriptionDoc struct {
|
|
ID bson.ObjectID `bson:"_id" json:"id"`
|
|
Slug string `bson:"slug" json:"slug"`
|
|
Name string `bson:"name" json:"name"`
|
|
Type string `bson:"type" json:"type"`
|
|
Date *string `bson:"date,omitempty" json:"date,omitempty"`
|
|
Year *int `bson:"year,omitempty" json:"year,omitempty"`
|
|
Month *int `bson:"month,omitempty" json:"month,omitempty"`
|
|
Day *int `bson:"day,omitempty" json:"day,omitempty"`
|
|
Place *string `bson:"place,omitempty" json:"place,omitempty"`
|
|
Context *string `bson:"context,omitempty" json:"context,omitempty"`
|
|
Reference *string `bson:"reference,omitempty" json:"reference,omitempty"`
|
|
DurationMinutes *int `bson:"durationMinutes,omitempty" json:"duration_minutes,omitempty"`
|
|
AudioUrl *string `bson:"audioUrl,omitempty" json:"audio_url,omitempty"`
|
|
Participants []string `bson:"participants" json:"participants"`
|
|
Content []ContentBlockDoc `bson:"content" json:"content"`
|
|
ContentJson *string `bson:"contentJson,omitempty" json:"-"`
|
|
Tags []string `bson:"tags" json:"tags"`
|
|
Language string `bson:"language" json:"language"`
|
|
Source *string `bson:"source,omitempty" json:"source,omitempty"`
|
|
IsPublished bool `bson:"isPublished" json:"is_published"`
|
|
}
|
|
|
|
type TranscriptionSummaryDoc struct {
|
|
ID bson.ObjectID `bson:"_id" json:"id"`
|
|
Slug string `bson:"slug" json:"slug"`
|
|
Name string `bson:"name" json:"name"`
|
|
Type string `bson:"type" json:"type"`
|
|
Date *string `bson:"date,omitempty" json:"date,omitempty"`
|
|
Year *int `bson:"year,omitempty" json:"year,omitempty"`
|
|
Month *int `bson:"month,omitempty" json:"month,omitempty"`
|
|
Day *int `bson:"day,omitempty" json:"day,omitempty"`
|
|
Place *string `bson:"place,omitempty" json:"place,omitempty"`
|
|
Context *string `bson:"context,omitempty" json:"context,omitempty"`
|
|
Reference *string `bson:"reference,omitempty" json:"reference,omitempty"`
|
|
DurationMinutes *int `bson:"durationMinutes,omitempty" json:"duration_minutes,omitempty"`
|
|
AudioUrl *string `bson:"audioUrl,omitempty" json:"audio_url,omitempty"`
|
|
Participants []string `bson:"participants" json:"participants"`
|
|
}
|
|
|
|
var publishedFilter = bson.M{"isPublished": true}
|
|
|
|
var transcriptionSummaryProjection = bson.M{
|
|
"slug": 1, "name": 1, "type": 1, "date": 1,
|
|
"year": 1, "month": 1, "day": 1, "place": 1,
|
|
"context": 1, "reference": 1, "durationMinutes": 1,
|
|
"audioUrl": 1, "participants": 1,
|
|
}
|
|
|
|
func (r *TranscriptionRepo) GetBySlug(ctx context.Context, slug string) (*TranscriptionDoc, error) {
|
|
filter := bson.M{"slug": slug, "isPublished": true}
|
|
var doc TranscriptionDoc
|
|
err := r.col.FindOne(ctx, filter).Decode(&doc)
|
|
if err != nil {
|
|
if err == mongo.ErrNoDocuments {
|
|
return nil, nil
|
|
}
|
|
return nil, err
|
|
}
|
|
if len(doc.Content) == 0 && doc.ContentJson != nil && *doc.ContentJson != "" {
|
|
var blocks []ContentBlockDoc
|
|
if err := json.Unmarshal([]byte(*doc.ContentJson), &blocks); err == nil {
|
|
doc.Content = blocks
|
|
}
|
|
}
|
|
doc.ContentJson = nil
|
|
return &doc, nil
|
|
}
|
|
|
|
func (r *TranscriptionRepo) GetByYear(ctx context.Context, year int) ([]TranscriptionSummaryDoc, error) {
|
|
filter := bson.M{"year": year, "isPublished": true}
|
|
opts := options.Find().
|
|
SetSort(bson.D{{Key: "month", Value: 1}, {Key: "day", Value: 1}}).
|
|
SetProjection(transcriptionSummaryProjection)
|
|
cursor, err := r.col.Find(ctx, filter, opts)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer cursor.Close(ctx)
|
|
var results []TranscriptionSummaryDoc
|
|
if err := cursor.All(ctx, &results); err != nil {
|
|
return nil, err
|
|
}
|
|
return results, nil
|
|
}
|
|
|
|
func (r *TranscriptionRepo) GetByPlace(ctx context.Context, place string) ([]TranscriptionSummaryDoc, error) {
|
|
filter := bson.M{"place": place, "isPublished": true}
|
|
opts := options.Find().
|
|
SetSort(bson.D{{Key: "year", Value: 1}, {Key: "month", Value: 1}, {Key: "day", Value: 1}}).
|
|
SetProjection(transcriptionSummaryProjection)
|
|
cursor, err := r.col.Find(ctx, filter, opts)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer cursor.Close(ctx)
|
|
var results []TranscriptionSummaryDoc
|
|
if err := cursor.All(ctx, &results); err != nil {
|
|
return nil, err
|
|
}
|
|
return results, nil
|
|
}
|
|
|
|
func (r *TranscriptionRepo) GetByType(ctx context.Context, docType string) ([]TranscriptionSummaryDoc, error) {
|
|
filter := bson.M{"type": docType, "isPublished": true}
|
|
opts := options.Find().
|
|
SetSort(bson.D{{Key: "year", Value: 1}, {Key: "month", Value: 1}, {Key: "day", Value: 1}}).
|
|
SetProjection(transcriptionSummaryProjection)
|
|
cursor, err := r.col.Find(ctx, filter, opts)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer cursor.Close(ctx)
|
|
var results []TranscriptionSummaryDoc
|
|
if err := cursor.All(ctx, &results); err != nil {
|
|
return nil, err
|
|
}
|
|
return results, nil
|
|
}
|
|
|
|
func (r *TranscriptionRepo) GetYears(ctx context.Context) ([]bson.M, error) {
|
|
pipeline := bson.A{
|
|
bson.M{"$match": bson.M{"isPublished": true, "year": bson.M{"$ne": nil}}},
|
|
bson.M{"$group": bson.M{"_id": "$year", "count": bson.M{"$sum": 1}}},
|
|
bson.M{"$sort": bson.M{"_id": 1}},
|
|
}
|
|
cursor, err := r.col.Aggregate(ctx, pipeline)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer cursor.Close(ctx)
|
|
var results []bson.M
|
|
if err := cursor.All(ctx, &results); err != nil {
|
|
return nil, err
|
|
}
|
|
return results, nil
|
|
}
|
|
|
|
func (r *TranscriptionRepo) GetPlaces(ctx context.Context) ([]bson.M, error) {
|
|
pipeline := bson.A{
|
|
bson.M{"$match": bson.M{"isPublished": true, "place": bson.M{"$ne": nil}}},
|
|
bson.M{"$group": bson.M{"_id": "$place", "count": bson.M{"$sum": 1}}},
|
|
bson.M{"$sort": bson.M{"count": -1}},
|
|
}
|
|
cursor, err := r.col.Aggregate(ctx, pipeline)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer cursor.Close(ctx)
|
|
var results []bson.M
|
|
if err := cursor.All(ctx, &results); err != nil {
|
|
return nil, err
|
|
}
|
|
return results, nil
|
|
}
|
|
|
|
func (r *TranscriptionRepo) GetTypeDistribution(ctx context.Context) (int64, int64, error) {
|
|
lectureCount, err := r.col.CountDocuments(ctx, bson.M{"type": "lecture", "isPublished": true})
|
|
if err != nil {
|
|
return 0, 0, err
|
|
}
|
|
conversationCount, err := r.col.CountDocuments(ctx, bson.M{"type": "conversation", "isPublished": true})
|
|
if err != nil {
|
|
return 0, 0, err
|
|
}
|
|
return lectureCount, conversationCount, nil
|
|
}
|
|
|
|
func (r *TranscriptionRepo) Count(ctx context.Context) (int64, error) {
|
|
return r.col.CountDocuments(ctx, publishedFilter)
|
|
}
|
|
|
|
func (r *TranscriptionRepo) GetAdjacent(ctx context.Context, slug string, year int) (*TranscriptionSummaryDoc, *TranscriptionSummaryDoc, error) {
|
|
filter := bson.M{"year": year, "isPublished": true}
|
|
opts := options.Find().
|
|
SetSort(bson.D{{Key: "month", Value: 1}, {Key: "day", Value: 1}}).
|
|
SetProjection(transcriptionSummaryProjection)
|
|
cursor, err := r.col.Find(ctx, filter, opts)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
defer cursor.Close(ctx)
|
|
var summaries []TranscriptionSummaryDoc
|
|
if err := cursor.All(ctx, &summaries); err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
idx := -1
|
|
for i, s := range summaries {
|
|
if s.Slug == slug {
|
|
idx = i
|
|
break
|
|
}
|
|
}
|
|
if idx < 0 {
|
|
return nil, nil, nil
|
|
}
|
|
|
|
var prev, next *TranscriptionSummaryDoc
|
|
if idx > 0 {
|
|
prev = &summaries[idx-1]
|
|
}
|
|
if idx < len(summaries)-1 {
|
|
next = &summaries[idx+1]
|
|
}
|
|
return prev, next, nil
|
|
}
|