106 lines
3.1 KiB
Go
106 lines
3.1 KiB
Go
package repository
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
|
|
"haixun-backend/internal/library/clock"
|
|
app "haixun-backend/internal/library/errors"
|
|
"haixun-backend/internal/library/errors/code"
|
|
libmongo "haixun-backend/internal/library/mongo"
|
|
"haixun-backend/internal/model/content_matrix/domain/entity"
|
|
domrepo "haixun-backend/internal/model/content_matrix/domain/repository"
|
|
|
|
"github.com/google/uuid"
|
|
"go.mongodb.org/mongo-driver/bson"
|
|
"go.mongodb.org/mongo-driver/mongo"
|
|
"go.mongodb.org/mongo-driver/mongo/options"
|
|
)
|
|
|
|
type mongoRepository struct {
|
|
collection *mongo.Collection
|
|
}
|
|
|
|
func NewMongoRepository(db *mongo.Database) domrepo.Repository {
|
|
if db == nil {
|
|
return &mongoRepository{}
|
|
}
|
|
return &mongoRepository{collection: db.Collection(entity.CollectionName)}
|
|
}
|
|
|
|
func (r *mongoRepository) EnsureIndexes(ctx context.Context) error {
|
|
if r.collection == nil {
|
|
return nil
|
|
}
|
|
return libmongo.EnsureIndexes(ctx, r.collection, []mongo.IndexModel{
|
|
{
|
|
Keys: bson.D{{Key: "tenant_id", Value: 1}, {Key: "owner_uid", Value: 1}, {Key: "brand_id", Value: 1}},
|
|
Options: options.Index().SetUnique(true).SetPartialFilterExpression(bson.M{"brand_id": bson.M{"$gt": ""}})},
|
|
{
|
|
Keys: bson.D{{Key: "tenant_id", Value: 1}, {Key: "owner_uid", Value: 1}, {Key: "persona_id", Value: 1}},
|
|
Options: options.Index().SetUnique(true).SetPartialFilterExpression(bson.M{"persona_id": bson.M{"$gt": ""}})},
|
|
})
|
|
}
|
|
|
|
func brandOwnerFilter(tenantID, ownerUID, brandID string) bson.M {
|
|
filter := bson.M{
|
|
"tenant_id": tenantID,
|
|
"owner_uid": ownerUID,
|
|
}
|
|
for k, v := range libmongo.BrandScopeFilter(brandID) {
|
|
filter[k] = v
|
|
}
|
|
return filter
|
|
}
|
|
|
|
func (r *mongoRepository) UpsertByBrand(ctx context.Context, matrix *entity.ContentMatrix) (*entity.ContentMatrix, error) {
|
|
if r.collection == nil {
|
|
return nil, app.For(code.Brand).DBUnavailable("Mongo is not configured")
|
|
}
|
|
now := clock.NowUnixNano()
|
|
matrix.UpdateAt = now
|
|
if matrix.CreateAt == 0 {
|
|
matrix.CreateAt = now
|
|
}
|
|
if strings.TrimSpace(matrix.ID) == "" {
|
|
matrix.ID = uuid.NewString()
|
|
}
|
|
filter := brandOwnerFilter(matrix.TenantID, matrix.OwnerUID, matrix.BrandID)
|
|
update := bson.M{
|
|
"$set": bson.M{
|
|
"rows": matrix.Rows,
|
|
"generated_at": matrix.GeneratedAt,
|
|
"update_at": matrix.UpdateAt,
|
|
"brand_id": matrix.BrandID,
|
|
},
|
|
"$setOnInsert": bson.M{
|
|
"_id": matrix.ID,
|
|
"tenant_id": matrix.TenantID,
|
|
"owner_uid": matrix.OwnerUID,
|
|
"create_at": matrix.CreateAt,
|
|
},
|
|
}
|
|
opts := options.FindOneAndUpdate().SetUpsert(true).SetReturnDocument(options.After)
|
|
var out entity.ContentMatrix
|
|
err := r.collection.FindOneAndUpdate(ctx, filter, update, opts).Decode(&out)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &out, nil
|
|
}
|
|
|
|
func (r *mongoRepository) GetByBrand(ctx context.Context, tenantID, ownerUID, brandID string) (*entity.ContentMatrix, error) {
|
|
if r.collection == nil {
|
|
return nil, app.For(code.Brand).DBUnavailable("Mongo is not configured")
|
|
}
|
|
var out entity.ContentMatrix
|
|
err := r.collection.FindOne(ctx, brandOwnerFilter(tenantID, ownerUID, brandID)).Decode(&out)
|
|
if err == mongo.ErrNoDocuments {
|
|
return nil, nil
|
|
}
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &out, nil
|
|
}
|