feat: add books APIs
This commit is contained in:
@@ -0,0 +1,211 @@
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user