Skip to content

Commit

Permalink
enable original key filter
Browse files Browse the repository at this point in the history
  • Loading branch information
tomokazu tantaka committed Nov 27, 2024
1 parent a7f7b61 commit 107d45d
Show file tree
Hide file tree
Showing 2 changed files with 178 additions and 163 deletions.
132 changes: 35 additions & 97 deletions mongox/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,38 +2,25 @@ package mongox

import "go.mongodb.org/mongo-driver/bson"

func AppendE(f interface{}, elements ...bson.E) interface{} {
switch f2 := f.(type) {
case bson.D:
for _, e := range elements {
f2 = append(f2, e)
}
return f2
func isEmptyCondition(condition interface{}) bool {
switch c := condition.(type) {
case bson.M:
f3 := make(bson.M, len(f2))
for k, v := range f2 {
f3[k] = v
}
for _, e := range elements {
f3[e.Key] = e.Value
}
return f3
}
return f
}

func GetE(f interface{}, k string) interface{} {
switch g := f.(type) {
return len(c) == 0
case bson.D:
for _, e := range g {
if e.Key == k {
return e.Value
}
}
case bson.M:
return g[k]
return len(c) == 0
case bson.A:
return len(c) == 0
case []bson.M:
return len(c) == 0
case []bson.D:
return len(c) == 0
case []bson.A:
return len(c) == 0
case []interface{}:
return len(c) == 0
default:
return false
}
return nil
}

func DToM(i interface{}) interface{} {
Expand Down Expand Up @@ -81,79 +68,30 @@ func DToM(i interface{}) interface{} {
return i
}

func AppendI(f interface{}, elements ...interface{}) interface{} {
switch f2 := f.(type) {
case []bson.D:
res := make([]interface{}, 0, len(f2))
for _, e := range f2 {
res = append(res, e)
}
return append(res, elements...)
case []bson.M:
res := make([]interface{}, 0, len(f2)+len(elements))
for _, e := range f2 {
res = append(res, e)
}
return append(res, elements...)
case bson.A:
res := make([]interface{}, 0, len(f2)+len(elements))
return append(res, append(f2, elements...)...)
case []interface{}:
res := make([]interface{}, 0, len(f2)+len(elements))
return append(res, append(f2, elements...)...)
}
return f
}

func And(filter interface{}, key string, f interface{}) interface{} {
if f == nil {
return filter
}
if g, ok := f.(bson.M); ok && g == nil {
return filter
}
if g, ok := f.(bson.D); ok && g == nil {
return filter
}
if g, ok := f.(bson.A); ok && g == nil {
return filter
}
if g, ok := f.([]interface{}); ok && g == nil {
return filter
}
if g, ok := f.([]bson.M); ok && g == nil {
return filter
}
if g, ok := f.([]bson.D); ok && g == nil {
return filter
}
if g, ok := f.([]bson.A); ok && g == nil {
func And(filter interface{}, key string, condition interface{}) interface{} {
if condition == nil || isEmptyCondition(condition) {
return filter
}

if key != "" && GetE(filter, key) != nil {
return filter
}
var g interface{}
if key == "" {
g = f
} else {
g = bson.M{key: f}
}
if GetE(filter, "$or") != nil {
return bson.M{
"$and": []interface{}{filter, g},
}
filterMap, ok := filter.(bson.M)
if !ok || len(filterMap) == 0 {
filterMap = bson.M{}
}
if and := GetE(filter, "$and"); and != nil {
return bson.M{
"$and": AppendI(and, g),

var newCondition interface{}
if key != "" {
if _, exists := filterMap[key]; exists {
return filter
}
newCondition = bson.M{key: condition}
} else {
newCondition = condition
}
if key == "" {
return bson.M{
"$and": []interface{}{filter, g},
}

if existingAnd, ok := filterMap["$and"].(bson.A); ok {
filterMap["$and"] = append(existingAnd, newCondition)
} else {
filterMap["$and"] = bson.A{newCondition}
}
return AppendE(filter, bson.E{Key: key, Value: f})
return filterMap
}
209 changes: 143 additions & 66 deletions mongox/util_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
"go.mongodb.org/mongo-driver/bson"
)

func TestConvertDToM(t *testing.T) {
func TestConvertdToM(t *testing.T) {
assert.Equal(t, bson.M{"a": "b"}, DToM(bson.M{"a": "b"}))
assert.Equal(t, bson.M{"a": "b"}, DToM(bson.D{{Key: "a", Value: "b"}}))
assert.Equal(t, []interface{}{bson.M{"a": "b"}}, DToM([]bson.D{{{Key: "a", Value: "b"}}}))
Expand All @@ -16,84 +16,161 @@ func TestConvertDToM(t *testing.T) {
assert.Equal(t, []interface{}{bson.M{"a": "b"}}, DToM([]interface{}{bson.D{{Key: "a", Value: "b"}}}))
}

func TestAppendI(t *testing.T) {
assert.Equal(t, []interface{}{bson.M{"a": "b"}, "x"}, AppendI([]bson.M{{"a": "b"}}, "x"))
assert.Equal(t, []interface{}{bson.D{{Key: "a", Value: "b"}}, "x"}, AppendI([]bson.D{{{Key: "a", Value: "b"}}}, "x"))
assert.Equal(t, []interface{}{bson.D{{Key: "a", Value: "b"}}, "x"}, AppendI(bson.A{bson.D{{Key: "a", Value: "b"}}}, "x"))
assert.Equal(t, []interface{}{bson.D{{Key: "a", Value: "b"}}, "x"}, AppendI([]interface{}{bson.D{{Key: "a", Value: "b"}}}, "x"))
func TestAndEmptyFilter(t *testing.T) {
filter := bson.M{}
expected := bson.M{
"$and": bson.A{
bson.M{"b": bson.M{"c": 2}},
},
}
actual := And(filter, "b", bson.M{"c": 2})
assert.Equal(t, expected, actual)
}

func TestAndEmptyKey(t *testing.T) {
filter := bson.M{"a": 1}
expected := bson.M{
"$and": bson.A{
bson.M{"c": 3},
},
"a": 1,
}
actual := And(filter, "", bson.M{"c": 3})
assert.Equal(t, expected, actual)
}

func TestAppendE(t *testing.T) {
assert.Equal(t, bson.M{"a": "b", "c": "d"}, AppendE(bson.M{"a": "b"}, bson.E{Key: "c", Value: "d"}))
assert.Equal(t, bson.D{{Key: "a", Value: "b"}, {Key: "c", Value: "d"}}, AppendE(bson.D{{Key: "a", Value: "b"}}, bson.E{Key: "c", Value: "d"}))
assert.Equal(t, []bson.M{}, AppendE([]bson.M{}, bson.E{Key: "c", Value: "d"}))
func TestAndExistingAnd(t *testing.T) {
filter := bson.M{
"$and": bson.A{
bson.M{"a": 1},
bson.M{"b": 2},
},
}
expected := bson.M{
"$and": bson.A{
bson.M{"a": 1},
bson.M{"b": 2},
bson.M{"c": bson.M{"d": 3}},
},
}
actual := And(filter, "c", bson.M{"d": 3})
assert.Equal(t, expected, actual)
}

func TestGetE(t *testing.T) {
assert.Equal(t, "b", GetE(bson.M{"a": "b"}, "a"))
assert.Nil(t, GetE(bson.M{"a": "b"}, "b"))
assert.Equal(t, "b", GetE(bson.D{{Key: "a", Value: "b"}}, "a"))
assert.Nil(t, GetE(bson.D{{Key: "a", Value: "b"}}, "b"))
assert.Nil(t, GetE(bson.A{}, "b"))
func TestAndWithOrAndEmptyKey(t *testing.T) {
filter := bson.M{
"$or": bson.A{
bson.M{"a": 1},
bson.M{"b": 2},
},
}
expected := bson.M{
"$and": bson.A{bson.M{"c": 3}},
"$or": bson.A{
bson.M{"a": 1},
bson.M{"b": 2},
},
}
actual := And(filter, "", bson.M{"c": 3})
assert.Equal(t, expected, actual)
}

func TestAnd(t *testing.T) {
assert.Equal(t, bson.M{"x": "y"}, And(bson.M{}, "x", "y"))
assert.Equal(t, bson.M{"x": "z"}, And(bson.M{"x": "z"}, "x", "y"))
assert.Equal(t, bson.M{"x": "z"}, And(bson.M{"x": "z"}, "", nil))
assert.Equal(t, bson.M{"x": "z"}, And(bson.M{"x": "z"}, "", bson.M(nil)))
assert.Equal(t, bson.M{"x": "z"}, And(bson.M{"x": "z"}, "", bson.D(nil)))
assert.Equal(t, bson.M{"x": "z"}, And(bson.M{"x": "z"}, "", bson.A(nil)))
assert.Equal(t, bson.M{"x": "z"}, And(bson.M{"x": "z"}, "", []bson.M(nil)))
assert.Equal(t, bson.M{"x": "z"}, And(bson.M{"x": "z"}, "", []bson.D(nil)))
assert.Equal(t, bson.M{"x": "z"}, And(bson.M{"x": "z"}, "", []bson.A(nil)))
assert.Equal(t, bson.M{"x": "z"}, And(bson.M{"x": "z"}, "", []interface{}(nil)))
assert.Equal(t, bson.M{
"$and": []interface{}{
bson.M{"$or": []bson.M{{"a": "b"}}},
bson.M{"x": "y"},
func TestAndComplexFilter(t *testing.T) {
filter := bson.M{
"$and": bson.A{
bson.M{"x": 10},
bson.M{"y": 20},
},
}, And(bson.M{"$or": []bson.M{{"a": "b"}}}, "x", "y"))
assert.Equal(t, bson.M{
"$and": []interface{}{
bson.M{"a": "b"},
bson.M{"x": "y"},
"$or": bson.A{
bson.M{"a": 1},
bson.M{"b": 2},
},
}, And(bson.M{"$and": []bson.M{{"a": "b"}}}, "x", "y"))
assert.Equal(t, bson.M{
"$and": []interface{}{
bson.M{"a": "b"},
bson.M{"x": "y"},
}
expected := bson.M{
"$and": bson.A{
bson.M{"x": 10},
bson.M{"y": 20},
bson.M{"c": bson.M{"d": 3}},
},
}, And(bson.M{"$and": []interface{}{bson.M{"a": "b"}}}, "x", "y"))
"$or": bson.A{bson.M{"a": 1},
bson.M{"b": 2},
},
}
actual := And(filter, "c", bson.M{"d": 3})
assert.Equal(t, expected, actual)
}

assert.Equal(t, bson.D{{Key: "x", Value: "y"}}, And(bson.D{}, "x", "y"))
assert.Equal(t, bson.D{{Key: "x", Value: "z"}}, And(bson.D{{Key: "x", Value: "z"}}, "x", "y"))
assert.Equal(t, bson.M{
"$and": []interface{}{
bson.D{{Key: "$or", Value: []bson.M{{"a": "b"}}}},
bson.M{"x": "y"},
func TestAndNilFilter(t *testing.T) {
var filter interface{}
expected := bson.M{
"$and": bson.A{
bson.M{"b": bson.M{"c": 2}},
},
}, And(bson.D{{Key: "$or", Value: []bson.M{{"a": "b"}}}}, "x", "y"))
assert.Equal(t, bson.M{
"$and": []interface{}{
bson.M{"a": "b"},
bson.M{"x": "y"},
}
actual := And(filter, "b", bson.M{"c": 2})
assert.Equal(t, expected, actual)
}

func TestAndEmptySliceCondition(t *testing.T) {
filter := bson.M{"a": 1}
expected := bson.M{"a": 1}
actual := And(filter, "b", bson.A{})
assert.Equal(t, expected, actual)
}

func TestAndProjectRefetchFilter(t *testing.T) {
team := "team_id_example"
last := "last_project_id"
updatedat := 1654849072592
filter := bson.M{
"$and": bson.A{
bson.M{
"$or": bson.A{
bson.M{"deleted": false},
bson.M{"deleted": bson.M{"$exists": false}},
},
},
bson.M{
"$or": bson.A{
bson.M{"coresupport": true},
bson.M{"coresupport": bson.M{"$exists": false}},
},
},
},
}, And(bson.D{{Key: "$and", Value: []bson.M{{"a": "b"}}}}, "x", "y"))
"team": team,
}

assert.Equal(t, bson.M{"$and": []interface{}{bson.M{}, "y"}}, And(bson.M{}, "", "y"))
assert.Equal(t, bson.M{"$and": []interface{}{bson.D{}, "y"}}, And(bson.D{}, "", "y"))
assert.Equal(t, bson.M{
"$and": []interface{}{
bson.D{{Key: "$or", Value: []bson.M{{"a": "b"}}}},
"y",
condition := bson.M{
"$or": bson.A{
bson.M{"updatedat": bson.M{"$lt": updatedat}},
bson.M{
"id": bson.M{"$lt": last},
"updatedat": updatedat,
},
},
}, And(bson.D{{Key: "$or", Value: []bson.M{{"a": "b"}}}}, "", "y"))
assert.Equal(t, bson.M{
"$and": []interface{}{
bson.M{"a": "b"},
"y",
}

expected := bson.M{
"$and": bson.A{
bson.M{"$or": bson.A{
bson.M{"deleted": false},
bson.M{"deleted": bson.M{"$exists": false}},
},
},
bson.M{"$or": bson.A{
bson.M{"coresupport": true},
bson.M{"coresupport": bson.M{"$exists": false}},
},
},
bson.M{"$or": bson.A{
bson.M{"updatedat": bson.M{"$lt": updatedat}},
bson.M{"id": bson.M{"$lt": last}, "updatedat": updatedat},
},
},
},
}, And(bson.D{{Key: "$and", Value: []bson.M{{"a": "b"}}}}, "", "y"))
"team": team,
}

actual := And(filter, "", condition)
assert.Equal(t, expected, actual)
}

0 comments on commit 107d45d

Please sign in to comment.