package pageopt import ( "reflect" "time" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/bson/primitive" ) // M M from Map type M = bson.M // Matcher type Matcher interface { Filter() M } // MergeM func MergeM(mats []Matcher) M { merge := M{} for _, m := range mats { if m == nil { continue } ql := m.Filter() for k, v := range ql { merge[k] = v } } return merge } type MergeMatch struct { merge M } func NewMergeMatch(mats ...Matcher) Matcher { mergeM := MergeM(mats) return &MergeMatch{mergeM} } func (m *MergeMatch) Filter() M { return m.merge } // AssignMatch type AssignMatch struct { Key string Val interface{} } func NewAssignMatch(key string, val interface{}) Matcher { return &AssignMatch{ key, val, } } func (m *AssignMatch) Filter() M { if IsEmpt(m.Val) { return M{} } return M{ m.Key: m.Val, } } // RegexMatch type RegexMatch struct { Key string Val interface{} Options string } func NewRegexMatch(key string, val interface{}, opt string) Matcher { return &RegexMatch{ Key: key, Val: val, Options: opt, } } func (r *RegexMatch) Filter() M { if IsEmpt(r.Val) { return M{} } return M{ r.Key: M{"$regex": r.Val, "$options": r.Options}, } } func IsNil(i interface{}) bool { vi := reflect.ValueOf(i) return vi.IsNil() } func IsEmpt(i interface{}) bool { v := reflect.ValueOf(i) switch v.Kind() { case reflect.Ptr: return v.IsNil() case reflect.Slice, reflect.Array: return v.Len() == 0 } return false } type NEMatch struct { Key string NE interface{} } func (m *NEMatch) Filter() M { if IsEmpt(m.NE) { return M{} } return M{m.Key: M{"$ne": m.NE}} } func NewNEMatch(Key string, ne interface{}) Matcher { return &NEMatch{ Key: Key, NE: ne, } } // GTEMatch type GTEMatch struct { Key string GTE interface{} } func NewGTEMatch(Key string, gte interface{}) Matcher { return >EMatch{ Key: Key, GTE: gte, } } func (m *GTEMatch) Filter() M { if IsEmpt(m.GTE) { return M{} } return M{m.Key: M{"$gte": m.GTE}} } // GTMatch type GTMatch struct { Key string GT interface{} } func NewGTMatch(Key string, gt interface{}) Matcher { return >Match{ Key: Key, GT: gt, } } func (m *GTMatch) Filter() M { if IsEmpt(m.GT) { return M{} } return M{m.Key: M{"$gt": m.GT}} } // LTMatch type LTMatch struct { Key string LT interface{} } func NewLTMatch(Key string, lt interface{}) Matcher { return <Match{ Key: Key, LT: lt, } } func (m *LTMatch) Filter() M { if IsEmpt(m.LT) { return M{} } return M{m.Key: M{"$lt": m.LT}} } // LTEMatch type LTEMatch struct { Key string LTE interface{} } func NewLTEMatch(Key string, lte interface{}) Matcher { return <EMatch{ Key: Key, LTE: lte, } } func (m *LTEMatch) Filter() M { if IsEmpt(m.LTE) { return M{} } return M{m.Key: M{"$lte": m.LTE}} } // GTEAndLTEMatch type GTEAndLTEMatch struct { Key string GTE interface{} LTE interface{} } func NewGTEAndLTEMatch(Key string, gte, lte interface{}) Matcher { return >EAndLTEMatch{ Key, gte, lte, } } func (m *GTEAndLTEMatch) Filter() M { if IsEmpt(m.GTE) || IsEmpt(m.LTE) { return M{} } return M{ m.Key: M{ "$gte": m.GTE, "$lte": m.LTE, }, } } // GTEAndLTMatch type GTEAndLTMatch struct { Key string GTE interface{} LT interface{} } func NewGTEAndLTMatch(key string, gte, lt interface{}) Matcher { return >EAndLTMatch{ Key: key, GTE: gte, LT: lt, } } func (m *GTEAndLTMatch) Filter() M { if IsEmpt(m.GTE) || IsEmpt(m.LT) { return M{} } return M{ m.Key: M{ "$gte": m.GTE, "$lt": m.LT, }, } } // ExistsMatch type ExistsMatch struct { Key string IsExisted *bool } func NewExistsMatch(key string, isExisted *bool) Matcher { return &ExistsMatch{ Key: key, IsExisted: isExisted, } } func (e *ExistsMatch) Filter() M { if IsEmpt(e.IsExisted) { return M{} } return M{ e.Key: M{"$exists": e.IsExisted}, } } // InMatch type InMatch struct { Key string Slice interface{} } func NewInMatch(key string, slice interface{}) Matcher { return &InMatch{ Key: key, Slice: slice, } } func (i *InMatch) Filter() M { if IsNil(i.Slice) { return M{} } return M{ i.Key: M{"$in": i.Slice}, } } // NinMatch type NinMatch struct { Key string Slice interface{} } func NewNinMatch(key string, slice interface{}) Matcher { return &NinMatch{ Key: key, Slice: slice, } } func (n *NinMatch) Filter() M { if IsNil(n.Slice) { return M{} } return M{ n.Key: M{"$nin": n.Slice}, } } // ManualOrMatch type ManualOrMatch struct { Key string Mats []Matcher } func NewManualOrMatch(key string, mats []Matcher) Matcher { return &ManualOrMatch{ Key: key, Mats: mats, } } func (o *ManualOrMatch) Filter() M { if len(o.Mats) == 0 { return M{} } fs := []interface{}{} for _, v := range o.Mats { f := v.Filter() if len(f) != 0 { fs = append(fs, v.Filter()) } } if len(fs) == 0 { return M{} } return M{"$or": fs} } // BitsAllSetMatch type BitsAllSetMatch struct { Key string Bits []int } func NewBitsAllSetMatch(key string, bits []int) Matcher { return &BitsAllSetMatch{ Key: key, Bits: bits, } } func (b *BitsAllSetMatch) Filter() M { if len(b.Bits) == 0 { return M{} } return M{ b.Key: M{"$bitsAllSet": b.Bits}, } } // BitsAllClearMatch type BitsAllClearMatch struct { Key string Bits []int } func NewBitsAllClearMatch(key string, bits []int) Matcher { return &BitsAllClearMatch{ Key: key, Bits: bits, } } func (b *BitsAllClearMatch) Filter() M { if len(b.Bits) == 0 { return M{} } return M{ b.Key: M{"$bitsAllClear": b.Bits}, } } // UIDMatch type UIDMatch struct { UID *uint64 } func (u *UIDMatch) New() Matcher { return NewAssignMatch("uid", u.UID) } // UIDInMatch type UIDInMatch struct { UIDS []uint64 } func (u *UIDInMatch) New() Matcher { return NewInMatch("uid", u.UIDS) } // IDMatch type IDMatch struct { ID *primitive.ObjectID } func (i *IDMatch) New() Matcher { return NewAssignMatch("_id", i.ID) } // IDInMatch type IDInMatch struct { IDs []primitive.ObjectID } func (c *IDInMatch) New() Matcher { return NewInMatch("_id", c.IDs) } // CreatedAtGTEMatch type CreatedAtGTEMatch struct { GTE *time.Time } func (c *CreatedAtGTEMatch) New() Matcher { return NewGTEMatch("createdAt", c.GTE) } // CreatedAtLTMatch type CreatedAtLTMatch struct { LT *time.Time } func (c *CreatedAtLTMatch) New() Matcher { return NewLTMatch("createdAt", c.LT) } // CreatedAtGTEAndLTMatch type CreatedAtGTEAndLTMatch struct { GTE *time.Time LT *time.Time } func (c *CreatedAtGTEAndLTMatch) New() Matcher { return NewGTEAndLTMatch("createdAt", c.GTE, c.LT) }