157 lines
3.8 KiB
Go
157 lines
3.8 KiB
Go
package builderimp
|
|
|
|
import (
|
|
"reflect"
|
|
|
|
"github.com/tech/sendico/pkg/db/repository/builder"
|
|
"github.com/tech/sendico/pkg/db/storable"
|
|
"go.mongodb.org/mongo-driver/bson"
|
|
"go.mongodb.org/mongo-driver/bson/primitive"
|
|
"go.mongodb.org/mongo-driver/mongo/options"
|
|
)
|
|
|
|
type QueryImp struct {
|
|
filter bson.D
|
|
sort bson.D
|
|
limit *int64
|
|
offset *int64
|
|
}
|
|
|
|
func (b *QueryImp) Filter(field builder.Field, value any) builder.Query {
|
|
b.filter = append(b.filter, bson.E{Key: field.Build(), Value: value})
|
|
return b
|
|
}
|
|
|
|
func (b *QueryImp) And(filters ...builder.Query) builder.Query {
|
|
andFilters := bson.A{}
|
|
for _, f := range filters {
|
|
andFilters = append(andFilters, f.BuildQuery())
|
|
}
|
|
b.filter = append(b.filter, bson.E{Key: string(builder.And), Value: andFilters})
|
|
return b
|
|
}
|
|
|
|
func (b *QueryImp) Or(filters ...builder.Query) builder.Query {
|
|
orFilters := bson.A{}
|
|
for _, f := range filters {
|
|
orFilters = append(orFilters, f.BuildQuery())
|
|
}
|
|
b.filter = append(b.filter, bson.E{Key: string(builder.Or), Value: orFilters})
|
|
return b
|
|
}
|
|
|
|
func (b *QueryImp) Comparison(field builder.Field, operator builder.MongoOperation, value any) builder.Query {
|
|
b.filter = append(b.filter, bson.E{Key: field.Build(), Value: bson.M{string(operator): value}})
|
|
return b
|
|
}
|
|
|
|
func (b *QueryImp) Expression(value builder.Expression) builder.Query {
|
|
b.filter = append(b.filter, bson.E{Key: string(builder.Expr), Value: value.Build()})
|
|
return b
|
|
}
|
|
|
|
func (b *QueryImp) RegEx(field builder.Field, pattern, options string) builder.Query {
|
|
b.filter = append(b.filter, bson.E{Key: field.Build(), Value: primitive.Regex{Pattern: pattern, Options: options}})
|
|
return b
|
|
}
|
|
|
|
func (b *QueryImp) opIn(field builder.Field, op builder.MongoOperation, values ...any) builder.Query {
|
|
var flattenedValues []any
|
|
|
|
for _, v := range values {
|
|
switch reflect.TypeOf(v).Kind() {
|
|
case reflect.Slice:
|
|
slice := reflect.ValueOf(v)
|
|
for i := range slice.Len() {
|
|
flattenedValues = append(flattenedValues, slice.Index(i).Interface())
|
|
}
|
|
default:
|
|
flattenedValues = append(flattenedValues, v)
|
|
}
|
|
}
|
|
|
|
b.filter = append(b.filter, bson.E{Key: field.Build(), Value: bson.M{string(op): flattenedValues}})
|
|
return b
|
|
}
|
|
|
|
func (b *QueryImp) NotIn(field builder.Field, values ...any) builder.Query {
|
|
return b.opIn(field, builder.NotIn, values...)
|
|
}
|
|
|
|
func (b *QueryImp) In(field builder.Field, values ...any) builder.Query {
|
|
return b.opIn(field, builder.In, values...)
|
|
}
|
|
|
|
func (b *QueryImp) Archived(isArchived *bool) builder.Query {
|
|
if isArchived == nil {
|
|
return b
|
|
}
|
|
return b.And(NewQueryImp().Filter(NewFieldImp(storable.IsArchivedField), *isArchived))
|
|
}
|
|
|
|
func (b *QueryImp) Sort(field builder.Field, ascending bool) builder.Query {
|
|
order := 1
|
|
if !ascending {
|
|
order = -1
|
|
}
|
|
b.sort = append(b.sort, bson.E{Key: field.Build(), Value: order})
|
|
return b
|
|
}
|
|
|
|
func (b *QueryImp) BuildPipeline() bson.D {
|
|
query := bson.D{}
|
|
|
|
if len(b.filter) > 0 {
|
|
query = append(query, bson.E{Key: string(builder.Match), Value: b.filter})
|
|
}
|
|
|
|
if len(b.sort) > 0 {
|
|
query = append(query, bson.E{Key: string(builder.Sort), Value: b.sort})
|
|
}
|
|
|
|
if b.limit != nil {
|
|
query = append(query, bson.E{Key: string(builder.Limit), Value: *b.limit})
|
|
}
|
|
|
|
if b.offset != nil {
|
|
query = append(query, bson.E{Key: string(builder.Skip), Value: *b.offset})
|
|
}
|
|
|
|
return query
|
|
}
|
|
|
|
func (b *QueryImp) BuildQuery() bson.D {
|
|
return b.filter
|
|
}
|
|
|
|
func (b *QueryImp) Limit(limit *int64) builder.Query {
|
|
b.limit = limit
|
|
return b
|
|
}
|
|
|
|
func (b *QueryImp) Offset(offset *int64) builder.Query {
|
|
b.offset = offset
|
|
return b
|
|
}
|
|
|
|
func (b *QueryImp) BuildOptions() *options.FindOptions {
|
|
opts := options.Find()
|
|
if b.limit != nil {
|
|
opts.SetLimit(*b.limit)
|
|
}
|
|
if b.offset != nil {
|
|
opts.SetSkip(*b.offset)
|
|
}
|
|
if len(b.sort) > 0 {
|
|
opts.SetSort(b.sort)
|
|
}
|
|
return opts
|
|
}
|
|
|
|
func NewQueryImp() builder.Query {
|
|
return &QueryImp{
|
|
filter: bson.D{},
|
|
sort: bson.D{},
|
|
}
|
|
}
|