diff --git a/pkg/expr/mongo.go b/pkg/expr/mongo.go index f856311d2f2856e5218260ba1fb8d6a58c457e0e..597180a671e80c2a5bc79bb8efd9bbee940120e4 100644 --- a/pkg/expr/mongo.go +++ b/pkg/expr/mongo.go @@ -673,27 +673,28 @@ func (c *compiler) handleLenNode(node *ast.BinaryNode) bson.M { panic("len() can only be compared with non-negative number") } + field := c.identifier(lenNode.Arguments[0]) switch op := node.Operator; { case (op == "==" || op == "<=") && length == 0: - return bson.M{c.identifier(lenNode.Arguments[0]): bson.M{"$eq": bson.A{}}} + return bson.M{field: bson.M{"$eq": bson.A{}}} case (op == "!=" || op == ">") && length == 0: - return bson.M{c.identifier(lenNode.Arguments[0]): bson.M{"$exists": true, "$type": "array", "$ne": bson.A{}}} + return bson.M{field: bson.M{"$exists": true, "$type": "array", "$ne": bson.A{}}} case op == ">=" && length == 0: - return bson.M{c.identifier(lenNode.Arguments[0]): bson.M{"$exists": true, "$type": "array"}} + return bson.M{field: bson.M{"$exists": true, "$type": "array"}} case op == "<" && length == 0: panic("invalid comparison: len() cannot be less than 0") case op == "==": - return bson.M{c.identifier(lenNode.Arguments[0]): bson.M{"$size": length}} + return bson.M{field: bson.M{"$size": length}} case op == "!=": - return bson.M{c.identifier(lenNode.Arguments[0]): bson.M{"$not": bson.M{"$size": length}}} + return bson.M{field: bson.M{"$not": bson.M{"$size": length}, "$type": "array"}} case op == ">": - return bson.M{c.identifier(lenNode.Arguments[0]) + "." + strconv.Itoa(length): bson.M{"$exists": true}} + return bson.M{field + "." + strconv.Itoa(length): bson.M{"$exists": true}} case op == ">=": - return bson.M{c.identifier(lenNode.Arguments[0]) + "." + strconv.Itoa(length-1): bson.M{"$exists": true}} + return bson.M{field + "." + strconv.Itoa(length-1): bson.M{"$exists": true}} case op == "<": - return bson.M{c.identifier(lenNode.Arguments[0]) + "." + strconv.Itoa(length-1): bson.M{"$exists": false}} + return bson.M{field + "." + strconv.Itoa(length-1): bson.M{"$exists": false}, field: bson.M{"$type": "array"}} case op == "<=": - return bson.M{c.identifier(lenNode.Arguments[0]) + "." + strconv.Itoa(length): bson.M{"$exists": false}} + return bson.M{field + "." + strconv.Itoa(length): bson.M{"$exists": false}, field: bson.M{"$type": "array"}} default: panic("invalid comparison operator with len()") } diff --git a/pkg/expr/mongo_test.go b/pkg/expr/mongo_test.go index 6420579ccd5eb013525ec20d34874e528974812c..dee6e668c490a6d375a77c532862f5389b1bd5f4 100644 --- a/pkg/expr/mongo_test.go +++ b/pkg/expr/mongo_test.go @@ -39,15 +39,15 @@ func TestConvertToMongo(t *testing.T) { {"len#5", "len(s) == s", nil, nil, true}, {"len eq", "len(s) == 1", nil, bson.M{"s": bson.M{"$size": 1}}, false}, {"len eq zero", "len(s) == 0", nil, bson.M{"s": bson.M{"$eq": bson.A{}}}, false}, - {"len ne", "len(s) != 1", nil, bson.M{"s": bson.M{"$not": bson.M{"$size": 1}}}, false}, + {"len ne", "len(s) != 1", nil, bson.M{"s": bson.M{"$not": bson.M{"$size": 1}, "$type": "array"}}, false}, {"len ne zero", "len(s) != 0", nil, bson.M{"s": bson.M{"$exists": true, "$ne": bson.A{}, "$type": "array"}}, false}, {"len gt", "len(s) > 1", nil, bson.M{"s.1": bson.M{"$exists": true}}, false}, {"len gt zero", "len(s) > 0", nil, bson.M{"s": bson.M{"$exists": true, "$type": "array", "$ne": bson.A{}}}, false}, {"len gte", "len(s) >= 1", nil, bson.M{"s.0": bson.M{"$exists": true}}, false}, {"len gte zero", "len(s) >= 0", nil, bson.M{"s": bson.M{"$exists": true, "$type": "array"}}, false}, - {"len lt", "len(s) < 1", nil, bson.M{"s.0": bson.M{"$exists": false}}, false}, + {"len lt", "len(s) < 1", nil, bson.M{"s.0": bson.M{"$exists": false}, "s": bson.M{"$type": "array"}}, false}, {"len lt zero", "len(s) < 0", nil, nil, true}, - {"len lte", "len(s) <= 1", nil, bson.M{"s.1": bson.M{"$exists": false}}, false}, + {"len lte", "len(s) <= 1", nil, bson.M{"s.1": bson.M{"$exists": false}, "s": bson.M{"$type": "array"}}, false}, {"len lte zero", "len(s) <= 0", nil, bson.M{"s": bson.M{"$eq": bson.A{}}}, false}, {"field#1", "s.test > 3", nil, bson.M{"s.test": bson.M{"$gt": 3}}, false}, {"field#2", "s['test'] > 3", nil, bson.M{"s.test": bson.M{"$gt": 3}}, false},