feat: add books APIs
This commit is contained in:
@@ -0,0 +1,160 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"go.mongodb.org/mongo-driver/v2/bson"
|
||||
"go.mongodb.org/mongo-driver/v2/mongo"
|
||||
"go.mongodb.org/mongo-driver/v2/mongo/options"
|
||||
)
|
||||
|
||||
type DiscipleRepo struct {
|
||||
col *mongo.Collection
|
||||
}
|
||||
|
||||
func NewDiscipleRepo(db *MongoDB) *DiscipleRepo {
|
||||
return &DiscipleRepo{col: db.Collection("disciples")}
|
||||
}
|
||||
|
||||
type DiscipleDoc struct {
|
||||
ID bson.ObjectID `bson:"_id" json:"id"`
|
||||
InitiatedName string `bson:"initiatedName" json:"initiated_name"`
|
||||
Suffix string `bson:"suffix" json:"suffix"`
|
||||
InitiationDate *time.Time `bson:"initiationDate,omitempty" json:"initiation_date,omitempty"`
|
||||
InitiationPlace *string `bson:"initiationPlace,omitempty" json:"initiation_place,omitempty"`
|
||||
KarmiName *string `bson:"karmiName,omitempty" json:"karmi_name,omitempty"`
|
||||
Avatar *string `bson:"avatar,omitempty" json:"avatar,omitempty"`
|
||||
About *string `bson:"about,omitempty" json:"about,omitempty"`
|
||||
Tags []string `bson:"tags" json:"tags"`
|
||||
IsVerified bool `bson:"isVerified" json:"is_verified"`
|
||||
}
|
||||
|
||||
type DiscipleSummaryDoc struct {
|
||||
ID bson.ObjectID `bson:"_id" json:"id"`
|
||||
InitiatedName string `bson:"initiatedName" json:"initiated_name"`
|
||||
Suffix string `bson:"suffix" json:"suffix"`
|
||||
InitiationDate *time.Time `bson:"initiationDate,omitempty" json:"initiation_date,omitempty"`
|
||||
InitiationPlace *string `bson:"initiationPlace,omitempty" json:"initiation_place,omitempty"`
|
||||
IsVerified bool `bson:"isVerified" json:"is_verified"`
|
||||
}
|
||||
|
||||
var discipleSummaryProjection = bson.M{
|
||||
"initiatedName": 1, "suffix": 1, "initiationDate": 1,
|
||||
"initiationPlace": 1, "isVerified": 1,
|
||||
}
|
||||
|
||||
func (r *DiscipleRepo) GetByLetter(ctx context.Context, letter string) ([]DiscipleSummaryDoc, error) {
|
||||
// Case-insensitive starts-with using regex
|
||||
filter := bson.M{"initiatedName": bson.M{"$regex": "^" + letter, "$options": "i"}}
|
||||
opts := options.Find().
|
||||
SetSort(bson.M{"initiatedName": 1}).
|
||||
SetProjection(discipleSummaryProjection)
|
||||
|
||||
cursor, err := r.col.Find(ctx, filter, opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer cursor.Close(ctx)
|
||||
var results []DiscipleSummaryDoc
|
||||
if err := cursor.All(ctx, &results); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (r *DiscipleRepo) GetByLetterAndSuffix(ctx context.Context, letter *string, suffix *string) ([]DiscipleSummaryDoc, error) {
|
||||
filter := bson.M{}
|
||||
if letter != nil {
|
||||
filter["initiatedName"] = bson.M{"$regex": "^" + *letter, "$options": "i"}
|
||||
}
|
||||
if suffix != nil && *suffix != "all" {
|
||||
filter["suffix"] = *suffix
|
||||
}
|
||||
|
||||
opts := options.Find().
|
||||
SetSort(bson.M{"initiatedName": 1}).
|
||||
SetProjection(discipleSummaryProjection)
|
||||
|
||||
cursor, err := r.col.Find(ctx, filter, opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer cursor.Close(ctx)
|
||||
var results []DiscipleSummaryDoc
|
||||
if err := cursor.All(ctx, &results); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (r *DiscipleRepo) Count(ctx context.Context) (int64, error) {
|
||||
return r.col.CountDocuments(ctx, bson.M{})
|
||||
}
|
||||
|
||||
func (r *DiscipleRepo) CountFiltered(ctx context.Context, letter *string, suffix *string) (int64, error) {
|
||||
filter := bson.M{}
|
||||
if letter != nil {
|
||||
filter["initiatedName"] = bson.M{"$regex": "^" + *letter, "$options": "i"}
|
||||
}
|
||||
if suffix != nil && *suffix != "all" {
|
||||
filter["suffix"] = *suffix
|
||||
}
|
||||
return r.col.CountDocuments(ctx, filter)
|
||||
}
|
||||
|
||||
func (r *DiscipleRepo) GetLetterCounts(ctx context.Context) ([]bson.M, error) {
|
||||
pipeline := bson.A{
|
||||
bson.M{"$group": bson.M{
|
||||
"_id": bson.M{"$toUpper": bson.M{"$substrBytes": bson.A{"$initiatedName", 0, 1}}},
|
||||
"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 *DiscipleRepo) GetSuffixCounts(ctx context.Context) ([]bson.M, error) {
|
||||
pipeline := bson.A{
|
||||
bson.M{"$group": bson.M{"_id": "$suffix", "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 *DiscipleRepo) Search(ctx context.Context, query string, limit int) ([]DiscipleSummaryDoc, error) {
|
||||
filter := bson.M{"initiatedName": bson.M{"$regex": query, "$options": "i"}}
|
||||
opts := options.Find().
|
||||
SetSort(bson.M{"initiatedName": 1}).
|
||||
SetLimit(int64(limit)).
|
||||
SetProjection(discipleSummaryProjection)
|
||||
|
||||
cursor, err := r.col.Find(ctx, filter, opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer cursor.Close(ctx)
|
||||
var results []DiscipleSummaryDoc
|
||||
if err := cursor.All(ctx, &results); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return results, nil
|
||||
}
|
||||
Reference in New Issue
Block a user