Files
2026-05-09 23:19:19 +05:30

212 lines
5.9 KiB
Go

package repository
import (
"context"
"go.mongodb.org/mongo-driver/v2/bson"
"go.mongodb.org/mongo-driver/v2/mongo"
"go.mongodb.org/mongo-driver/v2/mongo/options"
)
type BookRepo struct {
meta *mongo.Collection
verses *mongo.Collection
proseChapters *mongo.Collection
}
func NewBookRepo(db *MongoDB) *BookRepo {
return &BookRepo{
meta: db.Collection("book_meta"),
verses: db.Collection("verses"),
proseChapters: db.Collection("prose_chapters"),
}
}
// --- Book Meta ---
type BookMetaDoc struct {
ID bson.ObjectID `bson:"_id" json:"id"`
Book string `bson:"book" json:"book"`
Data interface{} `bson:"data" json:"data"`
}
func (r *BookRepo) GetAllBookMetas(ctx context.Context) ([]BookMetaDoc, error) {
cursor, err := r.meta.Find(ctx, bson.M{})
if err != nil {
return nil, err
}
defer cursor.Close(ctx)
var results []BookMetaDoc
if err := cursor.All(ctx, &results); err != nil {
return nil, err
}
return results, nil
}
func (r *BookRepo) GetBookMeta(ctx context.Context, book string) (*BookMetaDoc, error) {
var doc BookMetaDoc
err := r.meta.FindOne(ctx, bson.M{"book": book}).Decode(&doc)
if err != nil {
if err == mongo.ErrNoDocuments {
return nil, nil
}
return nil, err
}
return &doc, nil
}
// --- Verses ---
type SynonymDoc struct {
Word string `bson:"word" json:"word"`
Meanings []string `bson:"meanings" json:"meanings"`
}
type VerseDoc struct {
ID bson.ObjectID `bson:"_id" json:"id"`
Book string `bson:"book" json:"book"`
Division *string `bson:"division,omitempty" json:"division,omitempty"`
Chapter int `bson:"chapter" json:"chapter"`
Verse int `bson:"verse" json:"verse"`
VerseEnd *int `bson:"verseEnd,omitempty" json:"verse_end,omitempty"`
Reference string `bson:"reference" json:"reference"`
BookTitle string `bson:"bookTitle" json:"book_title"`
Devanagari string `bson:"devanagari" json:"devanagari"`
Bengali *string `bson:"bengali,omitempty" json:"bengali,omitempty"`
Transliteration string `bson:"transliteration" json:"transliteration"`
Synonyms []SynonymDoc `bson:"synonyms" json:"synonyms"`
Translation string `bson:"translation" json:"translation"`
Purport []string `bson:"purport" json:"purport"`
}
type VerseIndexDoc struct {
Verse int `bson:"verse" json:"verse"`
VerseEnd *int `bson:"verseEnd,omitempty" json:"verse_end,omitempty"`
Reference string `bson:"reference" json:"reference"`
}
func (r *BookRepo) GetVerseIndex(ctx context.Context, book string, division *string, chapter int) ([]VerseIndexDoc, error) {
filter := bson.M{"book": book, "chapter": chapter}
if division != nil {
filter["division"] = *division
} else {
filter["division"] = nil
}
opts := options.Find().
SetSort(bson.M{"verse": 1}).
SetProjection(bson.M{"_id": 0, "verse": 1, "verseEnd": 1, "reference": 1})
cursor, err := r.verses.Find(ctx, filter, opts)
if err != nil {
return nil, err
}
defer cursor.Close(ctx)
var results []VerseIndexDoc
if err := cursor.All(ctx, &results); err != nil {
return nil, err
}
return results, nil
}
func (r *BookRepo) GetVerses(ctx context.Context, book string, division *string, chapter int, page, limit int) ([]VerseDoc, int64, error) {
filter := bson.M{"book": book, "chapter": chapter}
if division != nil {
filter["division"] = *division
} else {
filter["division"] = nil
}
total, err := r.verses.CountDocuments(ctx, filter)
if err != nil {
return nil, 0, err
}
skip := int64((page - 1) * limit)
opts := options.Find().
SetSort(bson.M{"verse": 1}).
SetSkip(skip).
SetLimit(int64(limit))
cursor, err := r.verses.Find(ctx, filter, opts)
if err != nil {
return nil, 0, err
}
defer cursor.Close(ctx)
var results []VerseDoc
if err := cursor.All(ctx, &results); err != nil {
return nil, 0, err
}
return results, total, nil
}
func (r *BookRepo) GetSingleVerse(ctx context.Context, book string, division *string, chapter, verse int) (*VerseDoc, error) {
filter := bson.M{"book": book, "chapter": chapter, "verse": verse}
if division != nil {
filter["division"] = *division
} else {
filter["division"] = nil
}
var doc VerseDoc
err := r.verses.FindOne(ctx, filter).Decode(&doc)
if err != nil {
if err == mongo.ErrNoDocuments {
return nil, nil
}
return nil, err
}
return &doc, nil
}
// --- Prose Chapters ---
type ProseChapterDoc struct {
ID bson.ObjectID `bson:"_id" json:"id"`
Book string `bson:"book" json:"book"`
Volume int `bson:"volume" json:"volume"`
Chapter *int `bson:"chapter,omitempty" json:"chapter,omitempty"`
Title string `bson:"title" json:"title"`
Type string `bson:"type" json:"type"`
Slug string `bson:"slug" json:"slug"`
Order int `bson:"order" json:"order"`
Paragraphs []string `bson:"paragraphs" json:"paragraphs"`
}
func (r *BookRepo) GetProseChapters(ctx context.Context, book string, volume int, chapterType *string) ([]ProseChapterDoc, error) {
filter := bson.M{"book": book, "volume": volume}
if chapterType != nil {
filter["type"] = *chapterType
}
opts := options.Find().SetSort(bson.M{"order": 1})
cursor, err := r.proseChapters.Find(ctx, filter, opts)
if err != nil {
return nil, err
}
defer cursor.Close(ctx)
var results []ProseChapterDoc
if err := cursor.All(ctx, &results); err != nil {
return nil, err
}
return results, nil
}
func (r *BookRepo) GetProseChapter(ctx context.Context, book string, volume int, slug string) (*ProseChapterDoc, error) {
filter := bson.M{"book": book, "volume": volume, "slug": slug}
var doc ProseChapterDoc
err := r.proseChapters.FindOne(ctx, filter).Decode(&doc)
if err != nil {
if err == mongo.ErrNoDocuments {
return nil, nil
}
return nil, err
}
return &doc, nil
}