{"record":{"id":"030fa7ca82d52061","repo":"microsoft/semantic-kernel","slug":"unary-are-not-supported-in-mongodb-filters","errorCode":null,"errorMessage":"Unary +, -, ~ are not supported in MongoDB filters.","messagePattern":"Unary \\+, -, ~ are not supported in MongoDB filters\\.","errorType":"exception","errorClass":"NotImplementedError","httpStatus":null,"severity":"error","filePath":"python/semantic_kernel/connectors/mongodb.py","lineNumber":494,"sourceCode":"                        return {left: {\"$lt\": right}}\n                    case ast.LtE():\n                        return {left: {\"$lte\": right}}\n                raise NotImplementedError(f\"Unsupported operator: {type(op)}\")\n            case ast.BoolOp():\n                op = node.op  # type: ignore\n                values = [self._lambda_parser(v) for v in node.values]\n                if isinstance(op, ast.And):\n                    return {\"$and\": values}\n                if isinstance(op, ast.Or):\n                    return {\"$or\": values}\n                raise NotImplementedError(f\"Unsupported BoolOp: {type(op)}\")\n            case ast.UnaryOp():\n                match node.op:\n                    case ast.Not():\n                        operand = self._lambda_parser(node.operand)\n                        return {\"$not\": operand}\n                    case ast.UAdd() | ast.USub() | ast.Invert():\n                        raise NotImplementedError(\"Unary +, -, ~ are not supported in MongoDB filters.\")\n            case ast.Attribute():\n                # Only allow attributes that are in the data model\n                if node.attr not in self.definition.storage_names:\n                    raise VectorStoreOperationException(\n                        f\"Field '{node.attr}' not in data model (storage property names are used).\"\n                    )\n                return node.attr\n            case ast.Name():\n                # Only allow names that are in the data model\n                if node.id not in self.definition.storage_names:\n                    raise VectorStoreOperationException(\n                        f\"Field '{node.id}' not in data model (storage property names are used).\"\n                    )\n                return node.id\n            case ast.Constant():\n                return node.value\n        raise NotImplementedError(f\"Unsupported AST node: {type(node)}\")\n","sourceCodeStart":476,"sourceCodeEnd":512,"githubUrl":"https://github.com/microsoft/semantic-kernel/blob/c028a0c7dc4f0814cdcbaba9d998f187a41197bf/python/semantic_kernel/connectors/mongodb.py#L476-L512","documentation":"The MongoDB filter lambda parser handles unary operations but only supports logical `not` (translated to `$not`). Unary plus (`+x`), unary minus (`-x`), and bitwise invert (`~x`) are explicitly rejected because MongoDB filter documents have no meaningful representation for numeric sign-flipping or bitwise negation in a query predicate. The NotImplementedError is raised immediately when such a unary op is encountered.","triggerScenarios":"Writing a filter lambda that applies unary minus, plus, or invert to an operand, e.g. `lambda x: -x.amount > 0` or `lambda x: ~x.flags`.","commonSituations":"Developer tries to negate a numeric field inline in the filter predicate, or uses bitwise complement on a flags field. Common when porting filter logic from application code that performs arithmetic on field values before comparing.","solutions":["Move the sign/arithmetical transformation outside the filter; pre-compute the comparison value and compare the raw field against it, e.g. instead of `-x.amount > -10` use `x.amount < 10`.","Avoid bitwise operations in filter lambdas entirely; filter flags in application code after the query.","Restructure so the lambda only compares model fields directly against constant or computed values."],"exampleFix":"// before\ncollection.search(filter=lambda x: -x.score > threshold)\n// after\ncollection.search(filter=lambda x: x.score < -threshold)","handlingStrategy":"validation","validationCode":"import ast, inspect\ndef has_unsupported_unary(func):\n    tree = ast.parse(inspect.getsource(func))\n    for node in ast.walk(tree):\n        if isinstance(node, ast.UnaryOp) and isinstance(node.op, (ast.UAdd, ast.USub, ast.Invert)):\n            return True\n    return False","typeGuard":null,"tryCatchPattern":"try:\n    results = await collection.search(filter=my_lambda)\nexcept NotImplementedError as e:\n    if \"Unary\" in str(e):\n        # move sign-flip / bitwise logic outside the lambda\n        ...","preventionTips":["Avoid unary +, -, and ~ inside filter lambdas.","Pre-compute comparison values outside the lambda and compare raw fields against them.","Keep filter lambdas to simple field-vs-constant comparisons."],"tags":["mongodb","filter","lambda","ast","semantic-kernel"],"backgroundTag":null,"analyzedSha":"c028a0c7dc4f0814cdcbaba9d998f187a41197bf","analyzedAt":"2026-08-13T13:48:05.040Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}