mongo-aggro 0.1.0__py3-none-any.whl → 0.2.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. mongo_aggro/__init__.py +400 -0
  2. mongo_aggro/accumulators.py +30 -12
  3. mongo_aggro/base.py +49 -9
  4. mongo_aggro/expressions/__init__.py +396 -0
  5. mongo_aggro/expressions/arithmetic.py +329 -0
  6. mongo_aggro/expressions/array.py +425 -0
  7. mongo_aggro/expressions/base.py +180 -0
  8. mongo_aggro/expressions/bitwise.py +84 -0
  9. mongo_aggro/expressions/comparison.py +161 -0
  10. mongo_aggro/expressions/conditional.py +117 -0
  11. mongo_aggro/expressions/date.py +665 -0
  12. mongo_aggro/expressions/encrypted.py +116 -0
  13. mongo_aggro/expressions/logical.py +72 -0
  14. mongo_aggro/expressions/object.py +122 -0
  15. mongo_aggro/expressions/set.py +150 -0
  16. mongo_aggro/expressions/size.py +48 -0
  17. mongo_aggro/expressions/string.py +365 -0
  18. mongo_aggro/expressions/trigonometry.py +283 -0
  19. mongo_aggro/expressions/type.py +205 -0
  20. mongo_aggro/expressions/variable.py +73 -0
  21. mongo_aggro/expressions/window.py +327 -0
  22. mongo_aggro/operators/__init__.py +65 -0
  23. mongo_aggro/operators/array.py +41 -0
  24. mongo_aggro/operators/base.py +15 -0
  25. mongo_aggro/operators/bitwise.py +81 -0
  26. mongo_aggro/operators/comparison.py +82 -0
  27. mongo_aggro/operators/element.py +32 -0
  28. mongo_aggro/operators/geo.py +171 -0
  29. mongo_aggro/operators/logical.py +111 -0
  30. mongo_aggro/operators/misc.py +102 -0
  31. mongo_aggro/operators/regex.py +25 -0
  32. mongo_aggro/stages/__init__.py +110 -0
  33. mongo_aggro/stages/array.py +69 -0
  34. mongo_aggro/stages/change.py +109 -0
  35. mongo_aggro/stages/core.py +170 -0
  36. mongo_aggro/stages/geo.py +93 -0
  37. mongo_aggro/stages/group.py +154 -0
  38. mongo_aggro/stages/join.py +221 -0
  39. mongo_aggro/stages/misc.py +45 -0
  40. mongo_aggro/stages/output.py +136 -0
  41. mongo_aggro/stages/search.py +315 -0
  42. mongo_aggro/stages/session.py +111 -0
  43. mongo_aggro/stages/stats.py +152 -0
  44. mongo_aggro/stages/transform.py +136 -0
  45. mongo_aggro/stages/window.py +139 -0
  46. mongo_aggro-0.2.2.dist-info/METADATA +193 -0
  47. mongo_aggro-0.2.2.dist-info/RECORD +49 -0
  48. {mongo_aggro-0.1.0.dist-info → mongo_aggro-0.2.2.dist-info}/WHEEL +1 -1
  49. mongo_aggro/operators.py +0 -247
  50. mongo_aggro/stages.py +0 -990
  51. mongo_aggro-0.1.0.dist-info/METADATA +0 -537
  52. mongo_aggro-0.1.0.dist-info/RECORD +0 -9
  53. {mongo_aggro-0.1.0.dist-info → mongo_aggro-0.2.2.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,116 @@
1
+ """Encrypted string expression operators for MongoDB aggregation."""
2
+
3
+ from typing import Any
4
+
5
+ from pydantic import model_serializer
6
+
7
+ from mongo_aggro.base import serialize_value
8
+ from mongo_aggro.expressions.base import ExpressionBase
9
+
10
+
11
+ class EncStrContainsExpr(ExpressionBase):
12
+ """
13
+ $encStrContains expression - checks if encrypted string contains substring.
14
+
15
+ Used with Queryable Encryption for searching encrypted fields.
16
+
17
+ Example:
18
+ >>> EncStrContainsExpr(input=F("encryptedField"), substring="search").model_dump()
19
+ {"$encStrContains": {"input": "$encryptedField", "substring": "search"}}
20
+ """
21
+
22
+ input: Any
23
+ substring: Any
24
+
25
+ @model_serializer
26
+ def serialize(self) -> dict[str, Any]:
27
+ """Serialize to MongoDB $encStrContains expression."""
28
+ return {
29
+ "$encStrContains": {
30
+ "input": serialize_value(self.input),
31
+ "substring": serialize_value(self.substring),
32
+ }
33
+ }
34
+
35
+
36
+ class EncStrStartsWithExpr(ExpressionBase):
37
+ """
38
+ $encStrStartsWith expression - checks if encrypted string starts with prefix.
39
+
40
+ Used with Queryable Encryption for searching encrypted fields.
41
+
42
+ Example:
43
+ >>> EncStrStartsWithExpr(input=F("encryptedField"), prefix="abc").model_dump()
44
+ {"$encStrStartsWith": {"input": "$encryptedField", "prefix": "abc"}}
45
+ """
46
+
47
+ input: Any
48
+ prefix: Any
49
+
50
+ @model_serializer
51
+ def serialize(self) -> dict[str, Any]:
52
+ """Serialize to MongoDB $encStrStartsWith expression."""
53
+ return {
54
+ "$encStrStartsWith": {
55
+ "input": serialize_value(self.input),
56
+ "prefix": serialize_value(self.prefix),
57
+ }
58
+ }
59
+
60
+
61
+ class EncStrEndsWithExpr(ExpressionBase):
62
+ """
63
+ $encStrEndsWith expression - checks if encrypted string ends with suffix.
64
+
65
+ Used with Queryable Encryption for searching encrypted fields.
66
+
67
+ Example:
68
+ >>> EncStrEndsWithExpr(input=F("encryptedField"), suffix="xyz").model_dump()
69
+ {"$encStrEndsWith": {"input": "$encryptedField", "suffix": "xyz"}}
70
+ """
71
+
72
+ input: Any
73
+ suffix: Any
74
+
75
+ @model_serializer
76
+ def serialize(self) -> dict[str, Any]:
77
+ """Serialize to MongoDB $encStrEndsWith expression."""
78
+ return {
79
+ "$encStrEndsWith": {
80
+ "input": serialize_value(self.input),
81
+ "suffix": serialize_value(self.suffix),
82
+ }
83
+ }
84
+
85
+
86
+ class EncStrNormalizedEqExpr(ExpressionBase):
87
+ """
88
+ $encStrNormalizedEq expression - normalized equality for encrypted strings.
89
+
90
+ Used with Queryable Encryption for case-insensitive matching.
91
+
92
+ Example:
93
+ >>> EncStrNormalizedEqExpr(input=F("encryptedField"), value="test").model_dump()
94
+ {"$encStrNormalizedEq": {"input": "$encryptedField", "value": "test"}}
95
+ """
96
+
97
+ input: Any
98
+ value: Any
99
+
100
+ @model_serializer
101
+ def serialize(self) -> dict[str, Any]:
102
+ """Serialize to MongoDB $encStrNormalizedEq expression."""
103
+ return {
104
+ "$encStrNormalizedEq": {
105
+ "input": serialize_value(self.input),
106
+ "value": serialize_value(self.value),
107
+ }
108
+ }
109
+
110
+
111
+ __all__ = [
112
+ "EncStrContainsExpr",
113
+ "EncStrStartsWithExpr",
114
+ "EncStrEndsWithExpr",
115
+ "EncStrNormalizedEqExpr",
116
+ ]
@@ -0,0 +1,72 @@
1
+ """Logical expression operators for MongoDB aggregation."""
2
+
3
+ from typing import Any
4
+
5
+ from pydantic import model_serializer
6
+
7
+ from mongo_aggro.base import serialize_value
8
+ from mongo_aggro.expressions.base import ExpressionBase
9
+
10
+
11
+ class AndExpr(ExpressionBase):
12
+ """
13
+ $and expression operator - logical AND.
14
+
15
+ Example:
16
+ >>> AndExpr(conditions=[
17
+ ... EqExpr(left=F("a"), right=1),
18
+ ... GtExpr(left=F("b"), right=2)
19
+ ... ]).model_dump()
20
+ {"$and": [{"$eq": ["$a", 1]}, {"$gt": ["$b", 2]}]}
21
+ """
22
+
23
+ conditions: list[Any]
24
+
25
+ @model_serializer
26
+ def serialize(self) -> dict[str, Any]:
27
+ """Serialize to MongoDB $and expression."""
28
+ return {"$and": [serialize_value(c) for c in self.conditions]}
29
+
30
+
31
+ class OrExpr(ExpressionBase):
32
+ """
33
+ $or expression operator - logical OR.
34
+
35
+ Example:
36
+ >>> OrExpr(conditions=[
37
+ ... EqExpr(left=F("a"), right=1),
38
+ ... EqExpr(left=F("a"), right=2)
39
+ ... ]).model_dump()
40
+ {"$or": [{"$eq": ["$a", 1]}, {"$eq": ["$a", 2]}]}
41
+ """
42
+
43
+ conditions: list[Any]
44
+
45
+ @model_serializer
46
+ def serialize(self) -> dict[str, Any]:
47
+ """Serialize to MongoDB $or expression."""
48
+ return {"$or": [serialize_value(c) for c in self.conditions]}
49
+
50
+
51
+ class NotExpr(ExpressionBase):
52
+ """
53
+ $not expression operator - logical NOT.
54
+
55
+ Example:
56
+ >>> NotExpr(condition=EqExpr(left=F("a"), right=1)).model_dump()
57
+ {"$not": {"$eq": ["$a", 1]}}
58
+ """
59
+
60
+ condition: Any
61
+
62
+ @model_serializer
63
+ def serialize(self) -> dict[str, Any]:
64
+ """Serialize to MongoDB $not expression."""
65
+ return {"$not": serialize_value(self.condition)}
66
+
67
+
68
+ __all__ = [
69
+ "AndExpr",
70
+ "OrExpr",
71
+ "NotExpr",
72
+ ]
@@ -0,0 +1,122 @@
1
+ """Object expression operators for MongoDB aggregation."""
2
+
3
+ from typing import Any
4
+
5
+ from pydantic import model_serializer
6
+
7
+ from mongo_aggro.base import serialize_value
8
+ from mongo_aggro.expressions.base import ExpressionBase
9
+
10
+
11
+ class MergeObjectsExpr(ExpressionBase):
12
+ """
13
+ $mergeObjects expression operator - merges documents into one.
14
+
15
+ Example:
16
+ >>> MergeObjectsExpr(objects=[F("defaults"), F("overrides")]).model_dump()
17
+ {"$mergeObjects": ["$defaults", "$overrides"]}
18
+ """
19
+
20
+ objects: list[Any]
21
+
22
+ @model_serializer
23
+ def serialize(self) -> dict[str, Any]:
24
+ """Serialize to MongoDB $mergeObjects expression."""
25
+ return {"$mergeObjects": [serialize_value(o) for o in self.objects]}
26
+
27
+
28
+ class ObjectToArrayExpr(ExpressionBase):
29
+ """
30
+ $objectToArray expression operator - converts object to array of k/v pairs.
31
+
32
+ Example:
33
+ >>> ObjectToArrayExpr(input=F("doc")).model_dump()
34
+ {"$objectToArray": "$doc"}
35
+ """
36
+
37
+ input: Any
38
+
39
+ @model_serializer
40
+ def serialize(self) -> dict[str, Any]:
41
+ """Serialize to MongoDB $objectToArray expression."""
42
+ return {"$objectToArray": serialize_value(self.input)}
43
+
44
+
45
+ class ArrayToObjectExpr(ExpressionBase):
46
+ """
47
+ $arrayToObject expression operator - converts array of k/v pairs to object.
48
+
49
+ Example:
50
+ >>> ArrayToObjectExpr(input=F("pairs")).model_dump()
51
+ {"$arrayToObject": "$pairs"}
52
+ """
53
+
54
+ input: Any
55
+
56
+ @model_serializer
57
+ def serialize(self) -> dict[str, Any]:
58
+ """Serialize to MongoDB $arrayToObject expression."""
59
+ return {"$arrayToObject": serialize_value(self.input)}
60
+
61
+
62
+ class GetFieldExpr(ExpressionBase):
63
+ """
64
+ $getField expression operator - gets a field value by name.
65
+
66
+ Example:
67
+ >>> GetFieldExpr(field="status", input=F("doc")).model_dump()
68
+ {"$getField": {"field": "status", "input": "$doc"}}
69
+ """
70
+
71
+ field: Any
72
+ input: Any | None = None
73
+
74
+ @model_serializer
75
+ def serialize(self) -> dict[str, Any]:
76
+ """Serialize to MongoDB $getField expression."""
77
+ if self.input is None:
78
+ return {"$getField": serialize_value(self.field)}
79
+ return {
80
+ "$getField": {
81
+ "field": serialize_value(self.field),
82
+ "input": serialize_value(self.input),
83
+ }
84
+ }
85
+
86
+
87
+ class SetFieldExpr(ExpressionBase):
88
+ """
89
+ $setField expression operator - sets or adds a field in a document.
90
+
91
+ Example:
92
+ >>> SetFieldExpr(
93
+ ... field="status",
94
+ ... input=F("doc"),
95
+ ... value="active"
96
+ ... ).model_dump()
97
+ {"$setField": {"field": "status", "input": "$doc", "value": "active"}}
98
+ """
99
+
100
+ field: Any
101
+ input: Any
102
+ value: Any
103
+
104
+ @model_serializer
105
+ def serialize(self) -> dict[str, Any]:
106
+ """Serialize to MongoDB $setField expression."""
107
+ return {
108
+ "$setField": {
109
+ "field": serialize_value(self.field),
110
+ "input": serialize_value(self.input),
111
+ "value": serialize_value(self.value),
112
+ }
113
+ }
114
+
115
+
116
+ __all__ = [
117
+ "MergeObjectsExpr",
118
+ "ObjectToArrayExpr",
119
+ "ArrayToObjectExpr",
120
+ "GetFieldExpr",
121
+ "SetFieldExpr",
122
+ ]
@@ -0,0 +1,150 @@
1
+ """Set expression operators for MongoDB aggregation."""
2
+
3
+ from typing import Any
4
+
5
+ from pydantic import model_serializer
6
+
7
+ from mongo_aggro.base import serialize_value
8
+ from mongo_aggro.expressions.base import ExpressionBase
9
+
10
+
11
+ class SetUnionExpr(ExpressionBase):
12
+ """
13
+ $setUnion expression operator - returns union of arrays (unique values).
14
+
15
+ Example:
16
+ >>> SetUnionExpr(arrays=[F("tags1"), F("tags2")]).model_dump()
17
+ {"$setUnion": ["$tags1", "$tags2"]}
18
+ """
19
+
20
+ arrays: list[Any]
21
+
22
+ @model_serializer
23
+ def serialize(self) -> dict[str, Any]:
24
+ """Serialize to MongoDB $setUnion expression."""
25
+ return {"$setUnion": [serialize_value(a) for a in self.arrays]}
26
+
27
+
28
+ class SetIntersectionExpr(ExpressionBase):
29
+ """
30
+ $setIntersection expression operator - returns common elements.
31
+
32
+ Example:
33
+ >>> SetIntersectionExpr(arrays=[F("a"), F("b")]).model_dump()
34
+ {"$setIntersection": ["$a", "$b"]}
35
+ """
36
+
37
+ arrays: list[Any]
38
+
39
+ @model_serializer
40
+ def serialize(self) -> dict[str, Any]:
41
+ """Serialize to MongoDB $setIntersection expression."""
42
+ return {"$setIntersection": [serialize_value(a) for a in self.arrays]}
43
+
44
+
45
+ class SetDifferenceExpr(ExpressionBase):
46
+ """
47
+ $setDifference expression operator - returns elements in first not in second.
48
+
49
+ Example:
50
+ >>> SetDifferenceExpr(first=F("all"), second=F("excluded")).model_dump()
51
+ {"$setDifference": ["$all", "$excluded"]}
52
+ """
53
+
54
+ first: Any
55
+ second: Any
56
+
57
+ @model_serializer
58
+ def serialize(self) -> dict[str, Any]:
59
+ """Serialize to MongoDB $setDifference expression."""
60
+ return {
61
+ "$setDifference": [
62
+ serialize_value(self.first),
63
+ serialize_value(self.second),
64
+ ]
65
+ }
66
+
67
+
68
+ class SetEqualsExpr(ExpressionBase):
69
+ """
70
+ $setEquals expression operator - checks if arrays have same elements.
71
+
72
+ Example:
73
+ >>> SetEqualsExpr(arrays=[F("a"), F("b")]).model_dump()
74
+ {"$setEquals": ["$a", "$b"]}
75
+ """
76
+
77
+ arrays: list[Any]
78
+
79
+ @model_serializer
80
+ def serialize(self) -> dict[str, Any]:
81
+ """Serialize to MongoDB $setEquals expression."""
82
+ return {"$setEquals": [serialize_value(a) for a in self.arrays]}
83
+
84
+
85
+ class SetIsSubsetExpr(ExpressionBase):
86
+ """
87
+ $setIsSubset expression operator - checks if first is subset of second.
88
+
89
+ Example:
90
+ >>> SetIsSubsetExpr(first=F("small"), second=F("large")).model_dump()
91
+ {"$setIsSubset": ["$small", "$large"]}
92
+ """
93
+
94
+ first: Any
95
+ second: Any
96
+
97
+ @model_serializer
98
+ def serialize(self) -> dict[str, Any]:
99
+ """Serialize to MongoDB $setIsSubset expression."""
100
+ return {
101
+ "$setIsSubset": [
102
+ serialize_value(self.first),
103
+ serialize_value(self.second),
104
+ ]
105
+ }
106
+
107
+
108
+ class AnyElementTrueExpr(ExpressionBase):
109
+ """
110
+ $anyElementTrue expression operator - true if any array element is truthy.
111
+
112
+ Example:
113
+ >>> AnyElementTrueExpr(input=F("flags")).model_dump()
114
+ {"$anyElementTrue": "$flags"}
115
+ """
116
+
117
+ input: Any
118
+
119
+ @model_serializer
120
+ def serialize(self) -> dict[str, Any]:
121
+ """Serialize to MongoDB $anyElementTrue expression."""
122
+ return {"$anyElementTrue": serialize_value(self.input)}
123
+
124
+
125
+ class AllElementsTrueExpr(ExpressionBase):
126
+ """
127
+ $allElementsTrue expression operator - true if all array elements truthy.
128
+
129
+ Example:
130
+ >>> AllElementsTrueExpr(input=F("conditions")).model_dump()
131
+ {"$allElementsTrue": "$conditions"}
132
+ """
133
+
134
+ input: Any
135
+
136
+ @model_serializer
137
+ def serialize(self) -> dict[str, Any]:
138
+ """Serialize to MongoDB $allElementsTrue expression."""
139
+ return {"$allElementsTrue": serialize_value(self.input)}
140
+
141
+
142
+ __all__ = [
143
+ "SetUnionExpr",
144
+ "SetIntersectionExpr",
145
+ "SetDifferenceExpr",
146
+ "SetEqualsExpr",
147
+ "SetIsSubsetExpr",
148
+ "AnyElementTrueExpr",
149
+ "AllElementsTrueExpr",
150
+ ]
@@ -0,0 +1,48 @@
1
+ """Data size expression operators for MongoDB aggregation."""
2
+
3
+ from typing import Any
4
+
5
+ from pydantic import model_serializer
6
+
7
+ from mongo_aggro.base import serialize_value
8
+ from mongo_aggro.expressions.base import ExpressionBase
9
+
10
+
11
+ class BsonSizeExpr(ExpressionBase):
12
+ """
13
+ $bsonSize expression operator - returns size of document in bytes.
14
+
15
+ Example:
16
+ >>> BsonSizeExpr(input=F("doc")).model_dump()
17
+ {"$bsonSize": "$doc"}
18
+ """
19
+
20
+ input: Any
21
+
22
+ @model_serializer
23
+ def serialize(self) -> dict[str, Any]:
24
+ """Serialize to MongoDB $bsonSize expression."""
25
+ return {"$bsonSize": serialize_value(self.input)}
26
+
27
+
28
+ class BinarySizeExpr(ExpressionBase):
29
+ """
30
+ $binarySize expression operator - returns size of string/binary in bytes.
31
+
32
+ Example:
33
+ >>> BinarySizeExpr(input=F("data")).model_dump()
34
+ {"$binarySize": "$data"}
35
+ """
36
+
37
+ input: Any
38
+
39
+ @model_serializer
40
+ def serialize(self) -> dict[str, Any]:
41
+ """Serialize to MongoDB $binarySize expression."""
42
+ return {"$binarySize": serialize_value(self.input)}
43
+
44
+
45
+ __all__ = [
46
+ "BsonSizeExpr",
47
+ "BinarySizeExpr",
48
+ ]