Skip to content
Snippets Groups Projects
Commit 0f9144c5 authored by Pavel Antonov's avatar Pavel Antonov :asterisk:
Browse files

Merge branch 'feature/PRXS-2039-ConvertToMongoUpd' into 'master'

Изменить сигнатура функции ConvertToMongo для работы с массивом строк

See merge request perxis/perxis-go!167
parents 2d55e02b b42f9cc6
No related branches found
No related tags found
No related merge requests found
Subproject commit 63410745d6008eaa9d9b00626b5f5b6891ac9189 Subproject commit 78fe6a1ea7e2fe588e4107bf14ac85293b201163
...@@ -20,44 +20,55 @@ var geoTypes = map[string]string{ ...@@ -20,44 +20,55 @@ var geoTypes = map[string]string{
"polygon": "$polygon", "polygon": "$polygon",
} }
func ConvertToMongo(ctx context.Context, exp string, env map[string]interface{}, identifierRenameFn func(string) string, ops ...expr.Option) (b bson.M, err error) { type MongoExprConfig struct {
if exp == "" { Env map[string]any
IdentifierRenameFn func(s string) string
Ops []expr.Option
}
func ConvertToMongo(ctx context.Context, config *MongoExprConfig, expressions ...string) (b bson.M, err error) {
if len(expressions) == 0 {
return bson.M{}, nil return bson.M{}, nil
} }
tree, err := parser.Parse(exp) tree, err := parser.Parse("(" + strings.Join(expressions, ") && (") + ")")
if err != nil { if err != nil {
return nil, err return nil, err
} }
return convertToMongo(ctx, tree, env, identifierRenameFn, ops...) return convertToMongo(ctx, config, tree)
} }
func convertToMongo(ctx context.Context, tree *parser.Tree, env map[string]interface{}, identifierRenameFn func(string) string, ops ...expr.Option) (b bson.M, err error) { func convertToMongo(ctx context.Context, config *MongoExprConfig, tree *parser.Tree) (b bson.M, err error) {
defer func() { defer func() {
if r := recover(); r != nil { if r := recover(); r != nil {
err = fmt.Errorf("%v", r) err = fmt.Errorf("%v", r)
} }
}() }()
if config == nil {
config = new(MongoExprConfig)
}
env := config.Env
if env == nil { if env == nil {
env = make(map[string]interface{}) env = make(map[string]interface{})
} }
env[EnvContextKey] = ctx env[EnvContextKey] = ctx
config := GetDefaultConfig(env) exprConfig := GetDefaultConfig(env)
for _, op := range ops { for _, op := range config.Ops {
op(config) op(exprConfig)
} }
env = config.Env.(map[string]interface{}) env = exprConfig.Env.(map[string]interface{})
if len(config.Visitors) >= 0 { if len(exprConfig.Visitors) >= 0 {
for _, v := range config.Visitors { for _, v := range exprConfig.Visitors {
ast.Walk(&tree.Node, v) ast.Walk(&tree.Node, v)
} }
} }
c := &compiler{tree: tree, env: env, config: config, identifierRenameFn: identifierRenameFn} c := &compiler{tree: tree, env: env, config: exprConfig, identifierRenameFn: config.IdentifierRenameFn}
v, ok := c.compile(tree.Node).(bson.M) v, ok := c.compile(tree.Node).(bson.M)
if !ok || v == nil { if !ok || v == nil {
return nil, fmt.Errorf("invalid expression") return nil, fmt.Errorf("invalid expression")
......
...@@ -22,12 +22,14 @@ func TestConvertToMongo(t *testing.T) { ...@@ -22,12 +22,14 @@ func TestConvertToMongo(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
eval string eval any
env map[string]interface{} env map[string]interface{}
wantB bson.M wantB bson.M
wantErr bool wantErr bool
}{ }{
{"equal", "s == 3", nil, bson.M{"s": 3}, false}, {"equal", "s == 3", nil, bson.M{"s": 3}, false},
{"equal (with []string)", []string{"object.space_id == 'sp'", "object.organization_id == 'org'"}, nil, bson.M{"$and": bson.A{bson.M{"object.space_id": "sp"}, bson.M{"object.organization_id": "org"}}}, false},
{"equal (with nil []string)", nil, nil, bson.M{}, false},
{"in array", "s in [1,2,3]", nil, bson.M{"s": bson.M{"$in": []interface{}{1, 2, 3}}}, false}, {"in array", "s in [1,2,3]", nil, bson.M{"s": bson.M{"$in": []interface{}{1, 2, 3}}}, false},
{"not in array", "s not in [1,2,3]", nil, bson.M{"s": bson.M{"$nin": []interface{}{1, 2, 3}}}, false}, {"not in array", "s not in [1,2,3]", nil, bson.M{"s": bson.M{"$nin": []interface{}{1, 2, 3}}}, false},
{"exists#1", "exists(s)", nil, bson.M{"s": bson.M{"$exists": true}}, false}, {"exists#1", "exists(s)", nil, bson.M{"s": bson.M{"$exists": true}}, false},
...@@ -80,7 +82,17 @@ func TestConvertToMongo(t *testing.T) { ...@@ -80,7 +82,17 @@ func TestConvertToMongo(t *testing.T) {
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
gotB, err := ConvertToMongo(ctx, tt.eval, tt.env, nil)
var exprs []string
switch v := tt.eval.(type) {
case []string:
exprs = v
case string:
exprs = []string{v}
}
config := &MongoExprConfig{Env: tt.env}
gotB, err := ConvertToMongo(ctx, config, exprs...)
if tt.wantErr { if tt.wantErr {
require.Error(t, err) require.Error(t, err)
return return
...@@ -102,8 +114,10 @@ func BenchmarkConvertToMongo(b *testing.B) { ...@@ -102,8 +114,10 @@ func BenchmarkConvertToMongo(b *testing.B) {
exp := InStringArray("id", ids) exp := InStringArray("id", ids)
//fmt.Println(len(exp)) //fmt.Println(len(exp))
config := &MongoExprConfig{Ops: []expr.Option{expr.Patch(&testVisitor{})}}
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
_, _ = ConvertToMongo(ctx, exp, nil, nil, expr.Patch(&testVisitor{})) _, _ = ConvertToMongo(ctx, config, exp)
} }
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment