COMPLEX SEARCH

This commit is contained in:
mr
2024-08-01 09:13:10 +02:00
parent ad455e0e3a
commit 924a688a9d
14 changed files with 240 additions and 90 deletions

View File

@@ -1,9 +1,92 @@
package dbs
import (
"fmt"
"strings"
"go.mongodb.org/mongo-driver/bson"
)
type Operator int
const (
LIKE Operator = iota
EXISTS
IN
GTE
LTE
LT
GT
EQUAL
)
var str = [...]string{
"like",
"exists",
"in",
"gte",
"lte",
"lt",
"gt",
"equal",
}
func (m Operator) String() string {
return str[m]
}
func (m Operator) ToMongoOperator() string {
switch m {
case LIKE:
return "$regex"
case EXISTS:
return "$exists"
case IN:
return "$in"
case GTE:
return "$gte"
case GT:
return "$gt"
case LTE:
return "$lte"
case LT:
return "$lt"
case EQUAL:
return "$match"
default:
return "$regex"
}
}
func StringToOperator(s string) Operator {
for i, v := range str {
if v == s {
return Operator(i)
}
}
return LIKE
}
func ToValueOperator(operator Operator, value interface{}) interface{} {
if strings.TrimSpace(fmt.Sprintf("%v", value)) == "*" {
value = ""
}
if operator == LIKE {
return "(?i).*" + strings.TrimSpace(fmt.Sprintf("%v", value)) + ".*"
}
return value
}
type Filters struct {
And map[string]Filter `json:"and"`
Or map[string]Filter `json:"or"`
}
type Filter struct {
Operator string `json:"operator,omitempty"`
Value interface{} `json:"value,omitempty"`
}
type Input = map[string]interface{}
func InputToBson(i Input, isUpdate bool) bson.D {

View File

@@ -4,7 +4,6 @@ import (
"context"
"errors"
"fmt"
"strings"
"time"
"cloud.o-forge.io/core/oc-lib/dbs"
@@ -261,27 +260,35 @@ func (m *MongoDB) LoadOne(id string, collection_name string) (*mongo.SingleResul
return res, 200, nil
}
func (m *MongoDB) Search(search string, filter []string, collection_name string) (*mongo.Cursor, int, error) {
func (m *MongoDB) Search(filters dbs.Filters, collection_name string) (*mongo.Cursor, int, error) {
if err := m.createClient(mngoConfig.GetUrl()); err != nil {
return nil, 503, err
}
opts := options.Find()
opts.SetLimit(100)
if strings.TrimSpace(search) == "*" {
search = ""
}
search = ".*" + strings.TrimSpace(search) + ".*"
targetDBCollection := CollectionMap[collection_name]
list := []bson.M{}
for _, k := range filter {
list = append(list, bson.M{k: bson.M{"$regex": search, "$options": "i"}})
andList := []bson.E{}
for k, filter := range filters.And {
andList = append(andList, bson.E{Key: k, Value: bson.M{
dbs.StringToOperator(filter.Operator).ToMongoOperator(): dbs.ToValueOperator(dbs.StringToOperator(filter.Operator), filter.Value)}})
}
orList := []bson.M{}
for k, filter := range filters.Or {
orList = append(orList, bson.M{
k: bson.M{dbs.StringToOperator(filter.Operator).ToMongoOperator(): dbs.ToValueOperator(dbs.StringToOperator(filter.Operator), filter.Value)}})
}
MngoCtx, cancel = context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
f := bson.D{}
if len(andList) > 0 {
f = append(f, andList...)
}
if len(orList) > 0 {
f = append(f, bson.E{Key: "$or", Value: orList})
}
if cursor, err := targetDBCollection.Find(
MngoCtx,
bson.M{"$or": list},
f,
opts,
); err != nil {
return nil, 404, err
@@ -327,24 +334,3 @@ func (m *MongoDB) LoadAll(collection_name string) (*mongo.Cursor, int, error) {
}
return res, 200, nil
}
func (m *MongoDB) toOperator(operator string) string {
if operator == "like" {
return "$regex"
} else if operator == "exists" {
return "$exists"
} else if operator == "in" {
return "$in"
} else if operator == "gte" {
return "$gte"
} else if operator == "gt" {
return "$gt"
} else if operator == "lte" {
return "$lte"
} else if operator == "lt" {
return "$lt"
} else if operator == "eq" {
return "$match"
}
return operator
}