diff --git a/pkg/expr/mongo.go b/pkg/expr/mongo.go
index 397043c2fc9e99ad26498b3aecbf87280ac795a1..597180a671e80c2a5bc79bb8efd9bbee940120e4 100644
--- a/pkg/expr/mongo.go
+++ b/pkg/expr/mongo.go
@@ -4,6 +4,7 @@ import (
 	"context"
 	"fmt"
 	"regexp"
+	"strconv"
 	"strings"
 
 	"github.com/expr-lang/expr"
@@ -213,7 +214,7 @@ func (c *compiler) UnaryNode(node *ast.UnaryNode) interface{} {
 			return bson.M{c.identifier(nodeIn.Left): bson.M{"$nin": c.eval(nodeIn.Right)}}
 		}
 
-		return bson.M{"$not": c.compile(node.Node)}
+		return bson.M{"$nor": bson.A{c.compile(node.Node)}}
 	default:
 		panic(fmt.Sprintf("unknown operator (%v)", node.Operator))
 	}
@@ -230,6 +231,10 @@ func (c *compiler) identifier(node ast.Node) string {
 }
 
 func (c *compiler) BinaryNode(node *ast.BinaryNode) interface{} {
+	if result := c.handleLenNode(node); result != nil {
+		return result
+	}
+
 	switch node.Operator {
 	case "==":
 		return bson.M{c.identifier(node.Left): c.eval(node.Right)}
@@ -404,6 +409,12 @@ func (c *compiler) CallNode(node *ast.CallNode) interface{} {
 		}
 
 		return bson.M{fields: bson.M{"$in": array}}
+	case "exists":
+		if len(node.Arguments) != 1 {
+			panic("exists() expects exactly 1 argument")
+		}
+		field := c.identifier(node.Arguments[0])
+		return bson.M{field: bson.M{"$exists": true}}
 
 	case "icontains":
 		v := c.identifier(node.Arguments[0])
@@ -641,3 +652,50 @@ func (c *compiler) PairNode(node *ast.PairNode) interface{} {
 	//c.compile(node.Key)
 	//c.compile(node.Value)
 }
+
+// handleLenNode получает узел AST и возвращает запрос для mongo,
+// если узел представляет вызов функции len, и nil в противном случае.
+func (c *compiler) handleLenNode(node *ast.BinaryNode) bson.M {
+	lenNode, ok := node.Left.(*ast.BuiltinNode)
+	if !ok || lenNode.Name != "len" {
+		return nil
+	}
+
+	if len(lenNode.Arguments) != 1 {
+		panic("len() expects exactly 1 argument")
+	}
+
+	length, ok := c.eval(node.Right).(int)
+	if !ok {
+		panic("len() can only be compared with number value")
+	}
+	if length < 0 {
+		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{field: bson.M{"$eq": bson.A{}}}
+	case (op == "!=" || op == ">") && length == 0:
+		return bson.M{field: bson.M{"$exists": true, "$type": "array", "$ne": bson.A{}}}
+	case op == ">=" && length == 0:
+		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{field: bson.M{"$size": length}}
+	case op == "!=":
+		return bson.M{field: bson.M{"$not": bson.M{"$size": length}, "$type": "array"}}
+	case op == ">":
+		return bson.M{field + "." + strconv.Itoa(length): bson.M{"$exists": true}}
+	case op == ">=":
+		return bson.M{field + "." + strconv.Itoa(length-1): bson.M{"$exists": true}}
+	case op == "<":
+		return bson.M{field + "." + strconv.Itoa(length-1): bson.M{"$exists": false}, field: bson.M{"$type": "array"}}
+	case op == "<=":
+		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 dadf30e720ce88cd51591989dd4e0082f3f0883f..dee6e668c490a6d375a77c532862f5389b1bd5f4 100644
--- a/pkg/expr/mongo_test.go
+++ b/pkg/expr/mongo_test.go
@@ -30,6 +30,25 @@ func TestConvertToMongo(t *testing.T) {
 		{"equal", "s == 3", nil, bson.M{"s": 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},
+		{"exists#1", "exists(s)", nil, bson.M{"s": bson.M{"$exists": true}}, false},
+		{"exists#2", "exists(s, s)", nil, nil, true},
+		{"len#1", "len(s)", nil, nil, true},
+		{"len#2", "len(s) <> 1", nil, nil, true},
+		{"len#3", "len(s) == -1", nil, nil, true},
+		{"len#4", "len(s, s) == -1", nil, nil, true},
+		{"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}, "$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}, "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}, "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},
 		{"field#3", "s[test] > 3", nil, bson.M{"s.test": bson.M{"$gt": 3}}, false},
@@ -46,6 +65,8 @@ func TestConvertToMongo(t *testing.T) {
 		{"iendsWith", "iendsWith(s, 'some')", nil, bson.M{"s": bson.M{"$regex": ".*some$", "$options": "i"}}, false},
 		{"iendsWith . + () $ {} ^", "iendsWith(s,'. + () $ {} ^')", nil, bson.M{"s": bson.M{"$regex": ".*\\. \\+ \\(\\) \\$ \\{\\} \\^$", "$options": "i"}}, false},
 		{"or", "s==2 || s > 10", nil, bson.M{"$or": bson.A{bson.M{"s": 2}, bson.M{"s": bson.M{"$gt": 10}}}}, false},
+		{"not#1", "not icontains(s, 'some')", nil, bson.M{"$nor": bson.A{bson.M{"s": bson.M{"$options": "i", "$regex": "some"}}}}, false},
+		{"not#2", "not (s.test > 3)", nil, bson.M{"$nor": bson.A{bson.M{"s.test": bson.M{"$gt": 3}}}}, false},
 		{"search", "search('some') || s > 10", nil, bson.M{"$or": bson.A{bson.M{"$text": bson.M{"$search": "some"}}, bson.M{"s": bson.M{"$gt": 10}}}}, false},
 		{"vars:or", "s== a + 2 || s > a + 10", map[string]interface{}{"a": 100}, bson.M{"$or": bson.A{bson.M{"s": 102}, bson.M{"s": bson.M{"$gt": 110}}}}, false},
 		{"near", "near(a, [55.5, 37.5], 1000)", map[string]interface{}{"a": []interface{}{55, 37}}, bson.M{"a.geometry": bson.M{"$near": bson.D{{Key: "$geometry", Value: map[string]interface{}{"coordinates": []interface{}{55.5, 37.5}, "type": "Point"}}, {Key: "$maxDistance", Value: 1000}}}}, false},