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.
- mongo_aggro/__init__.py +400 -0
- mongo_aggro/accumulators.py +30 -12
- mongo_aggro/base.py +49 -9
- mongo_aggro/expressions/__init__.py +396 -0
- mongo_aggro/expressions/arithmetic.py +329 -0
- mongo_aggro/expressions/array.py +425 -0
- mongo_aggro/expressions/base.py +180 -0
- mongo_aggro/expressions/bitwise.py +84 -0
- mongo_aggro/expressions/comparison.py +161 -0
- mongo_aggro/expressions/conditional.py +117 -0
- mongo_aggro/expressions/date.py +665 -0
- mongo_aggro/expressions/encrypted.py +116 -0
- mongo_aggro/expressions/logical.py +72 -0
- mongo_aggro/expressions/object.py +122 -0
- mongo_aggro/expressions/set.py +150 -0
- mongo_aggro/expressions/size.py +48 -0
- mongo_aggro/expressions/string.py +365 -0
- mongo_aggro/expressions/trigonometry.py +283 -0
- mongo_aggro/expressions/type.py +205 -0
- mongo_aggro/expressions/variable.py +73 -0
- mongo_aggro/expressions/window.py +327 -0
- mongo_aggro/operators/__init__.py +65 -0
- mongo_aggro/operators/array.py +41 -0
- mongo_aggro/operators/base.py +15 -0
- mongo_aggro/operators/bitwise.py +81 -0
- mongo_aggro/operators/comparison.py +82 -0
- mongo_aggro/operators/element.py +32 -0
- mongo_aggro/operators/geo.py +171 -0
- mongo_aggro/operators/logical.py +111 -0
- mongo_aggro/operators/misc.py +102 -0
- mongo_aggro/operators/regex.py +25 -0
- mongo_aggro/stages/__init__.py +110 -0
- mongo_aggro/stages/array.py +69 -0
- mongo_aggro/stages/change.py +109 -0
- mongo_aggro/stages/core.py +170 -0
- mongo_aggro/stages/geo.py +93 -0
- mongo_aggro/stages/group.py +154 -0
- mongo_aggro/stages/join.py +221 -0
- mongo_aggro/stages/misc.py +45 -0
- mongo_aggro/stages/output.py +136 -0
- mongo_aggro/stages/search.py +315 -0
- mongo_aggro/stages/session.py +111 -0
- mongo_aggro/stages/stats.py +152 -0
- mongo_aggro/stages/transform.py +136 -0
- mongo_aggro/stages/window.py +139 -0
- mongo_aggro-0.2.2.dist-info/METADATA +193 -0
- mongo_aggro-0.2.2.dist-info/RECORD +49 -0
- {mongo_aggro-0.1.0.dist-info → mongo_aggro-0.2.2.dist-info}/WHEEL +1 -1
- mongo_aggro/operators.py +0 -247
- mongo_aggro/stages.py +0 -990
- mongo_aggro-0.1.0.dist-info/METADATA +0 -537
- mongo_aggro-0.1.0.dist-info/RECORD +0 -9
- {mongo_aggro-0.1.0.dist-info → mongo_aggro-0.2.2.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
"""Comparison 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 EqExpr(ExpressionBase):
|
|
12
|
+
"""
|
|
13
|
+
$eq expression operator - tests equality.
|
|
14
|
+
|
|
15
|
+
Example:
|
|
16
|
+
>>> EqExpr(left=F("status"), right="active").model_dump()
|
|
17
|
+
{"$eq": ["$status", "active"]}
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
left: Any
|
|
21
|
+
right: Any
|
|
22
|
+
|
|
23
|
+
@model_serializer
|
|
24
|
+
def serialize(self) -> dict[str, Any]:
|
|
25
|
+
"""Serialize to MongoDB $eq expression."""
|
|
26
|
+
return {
|
|
27
|
+
"$eq": [serialize_value(self.left), serialize_value(self.right)]
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class NeExpr(ExpressionBase):
|
|
32
|
+
"""
|
|
33
|
+
$ne expression operator - tests inequality.
|
|
34
|
+
|
|
35
|
+
Example:
|
|
36
|
+
>>> NeExpr(left=F("status"), right="deleted").model_dump()
|
|
37
|
+
{"$ne": ["$status", "deleted"]}
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
left: Any
|
|
41
|
+
right: Any
|
|
42
|
+
|
|
43
|
+
@model_serializer
|
|
44
|
+
def serialize(self) -> dict[str, Any]:
|
|
45
|
+
"""Serialize to MongoDB $ne expression."""
|
|
46
|
+
return {
|
|
47
|
+
"$ne": [serialize_value(self.left), serialize_value(self.right)]
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class GtExpr(ExpressionBase):
|
|
52
|
+
"""
|
|
53
|
+
$gt expression operator - tests greater than.
|
|
54
|
+
|
|
55
|
+
Example:
|
|
56
|
+
>>> GtExpr(left=F("age"), right=18).model_dump()
|
|
57
|
+
{"$gt": ["$age", 18]}
|
|
58
|
+
"""
|
|
59
|
+
|
|
60
|
+
left: Any
|
|
61
|
+
right: Any
|
|
62
|
+
|
|
63
|
+
@model_serializer
|
|
64
|
+
def serialize(self) -> dict[str, Any]:
|
|
65
|
+
"""Serialize to MongoDB $gt expression."""
|
|
66
|
+
return {
|
|
67
|
+
"$gt": [serialize_value(self.left), serialize_value(self.right)]
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
class GteExpr(ExpressionBase):
|
|
72
|
+
"""
|
|
73
|
+
$gte expression operator - tests greater than or equal.
|
|
74
|
+
|
|
75
|
+
Example:
|
|
76
|
+
>>> GteExpr(left=F("age"), right=18).model_dump()
|
|
77
|
+
{"$gte": ["$age", 18]}
|
|
78
|
+
"""
|
|
79
|
+
|
|
80
|
+
left: Any
|
|
81
|
+
right: Any
|
|
82
|
+
|
|
83
|
+
@model_serializer
|
|
84
|
+
def serialize(self) -> dict[str, Any]:
|
|
85
|
+
"""Serialize to MongoDB $gte expression."""
|
|
86
|
+
return {
|
|
87
|
+
"$gte": [serialize_value(self.left), serialize_value(self.right)]
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
class LtExpr(ExpressionBase):
|
|
92
|
+
"""
|
|
93
|
+
$lt expression operator - tests less than.
|
|
94
|
+
|
|
95
|
+
Example:
|
|
96
|
+
>>> LtExpr(left=F("age"), right=65).model_dump()
|
|
97
|
+
{"$lt": ["$age", 65]}
|
|
98
|
+
"""
|
|
99
|
+
|
|
100
|
+
left: Any
|
|
101
|
+
right: Any
|
|
102
|
+
|
|
103
|
+
@model_serializer
|
|
104
|
+
def serialize(self) -> dict[str, Any]:
|
|
105
|
+
"""Serialize to MongoDB $lt expression."""
|
|
106
|
+
return {
|
|
107
|
+
"$lt": [serialize_value(self.left), serialize_value(self.right)]
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
class LteExpr(ExpressionBase):
|
|
112
|
+
"""
|
|
113
|
+
$lte expression operator - tests less than or equal.
|
|
114
|
+
|
|
115
|
+
Example:
|
|
116
|
+
>>> LteExpr(left=F("age"), right=65).model_dump()
|
|
117
|
+
{"$lte": ["$age", 65]}
|
|
118
|
+
"""
|
|
119
|
+
|
|
120
|
+
left: Any
|
|
121
|
+
right: Any
|
|
122
|
+
|
|
123
|
+
@model_serializer
|
|
124
|
+
def serialize(self) -> dict[str, Any]:
|
|
125
|
+
"""Serialize to MongoDB $lte expression."""
|
|
126
|
+
return {
|
|
127
|
+
"$lte": [serialize_value(self.left), serialize_value(self.right)]
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
class CmpExpr(ExpressionBase):
|
|
132
|
+
"""
|
|
133
|
+
$cmp expression operator - compares two values.
|
|
134
|
+
|
|
135
|
+
Returns -1 if first < second, 0 if equal, 1 if first > second.
|
|
136
|
+
|
|
137
|
+
Example:
|
|
138
|
+
>>> CmpExpr(left=F("a"), right=F("b")).model_dump()
|
|
139
|
+
{"$cmp": ["$a", "$b"]}
|
|
140
|
+
"""
|
|
141
|
+
|
|
142
|
+
left: Any
|
|
143
|
+
right: Any
|
|
144
|
+
|
|
145
|
+
@model_serializer
|
|
146
|
+
def serialize(self) -> dict[str, Any]:
|
|
147
|
+
"""Serialize to MongoDB $cmp expression."""
|
|
148
|
+
return {
|
|
149
|
+
"$cmp": [serialize_value(self.left), serialize_value(self.right)]
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
__all__ = [
|
|
154
|
+
"EqExpr",
|
|
155
|
+
"NeExpr",
|
|
156
|
+
"GtExpr",
|
|
157
|
+
"GteExpr",
|
|
158
|
+
"LtExpr",
|
|
159
|
+
"LteExpr",
|
|
160
|
+
"CmpExpr",
|
|
161
|
+
]
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
"""Conditional expression operators for MongoDB aggregation."""
|
|
2
|
+
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
from pydantic import BaseModel, ConfigDict, model_serializer
|
|
6
|
+
|
|
7
|
+
from mongo_aggro.base import serialize_value
|
|
8
|
+
from mongo_aggro.expressions.base import ExpressionBase
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class CondExpr(ExpressionBase):
|
|
12
|
+
"""
|
|
13
|
+
$cond expression operator - ternary conditional.
|
|
14
|
+
|
|
15
|
+
Example:
|
|
16
|
+
>>> CondExpr(
|
|
17
|
+
... if_=GtExpr(left=F("qty"), right=100),
|
|
18
|
+
... then="bulk",
|
|
19
|
+
... else_="retail"
|
|
20
|
+
... ).model_dump()
|
|
21
|
+
{"$cond": {"if": {"$gt": ["$qty", 100]}, "then": "bulk", "else": "retail"}}
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
if_: Any
|
|
25
|
+
then: Any
|
|
26
|
+
else_: Any
|
|
27
|
+
|
|
28
|
+
@model_serializer
|
|
29
|
+
def serialize(self) -> dict[str, Any]:
|
|
30
|
+
"""Serialize to MongoDB $cond expression."""
|
|
31
|
+
return {
|
|
32
|
+
"$cond": {
|
|
33
|
+
"if": serialize_value(self.if_),
|
|
34
|
+
"then": serialize_value(self.then),
|
|
35
|
+
"else": serialize_value(self.else_),
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class IfNullExpr(ExpressionBase):
|
|
41
|
+
"""
|
|
42
|
+
$ifNull expression operator - null coalescing.
|
|
43
|
+
|
|
44
|
+
Example:
|
|
45
|
+
>>> IfNullExpr(input=F("name"), replacement="Unknown").model_dump()
|
|
46
|
+
{"$ifNull": ["$name", "Unknown"]}
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
input: Any
|
|
50
|
+
replacement: Any
|
|
51
|
+
|
|
52
|
+
@model_serializer
|
|
53
|
+
def serialize(self) -> dict[str, Any]:
|
|
54
|
+
"""Serialize to MongoDB $ifNull expression."""
|
|
55
|
+
return {
|
|
56
|
+
"$ifNull": [
|
|
57
|
+
serialize_value(self.input),
|
|
58
|
+
serialize_value(self.replacement),
|
|
59
|
+
]
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
class SwitchBranch(BaseModel):
|
|
64
|
+
"""A single branch in a $switch expression."""
|
|
65
|
+
|
|
66
|
+
model_config = ConfigDict(
|
|
67
|
+
populate_by_name=True,
|
|
68
|
+
extra="forbid",
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
case: Any
|
|
72
|
+
then: Any
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
class SwitchExpr(ExpressionBase):
|
|
76
|
+
"""
|
|
77
|
+
$switch expression operator - multi-branch conditional.
|
|
78
|
+
|
|
79
|
+
Example:
|
|
80
|
+
>>> SwitchExpr(
|
|
81
|
+
... branches=[
|
|
82
|
+
... SwitchBranch(case=EqExpr(left=F("status"), right="A"), then=1),
|
|
83
|
+
... SwitchBranch(case=EqExpr(left=F("status"), right="B"), then=2),
|
|
84
|
+
... ],
|
|
85
|
+
... default=0
|
|
86
|
+
... ).model_dump()
|
|
87
|
+
{"$switch": {"branches": [...], "default": 0}}
|
|
88
|
+
"""
|
|
89
|
+
|
|
90
|
+
branches: list[SwitchBranch]
|
|
91
|
+
default: Any = None
|
|
92
|
+
|
|
93
|
+
@model_serializer
|
|
94
|
+
def serialize(self) -> dict[str, Any]:
|
|
95
|
+
"""Serialize to MongoDB $switch expression."""
|
|
96
|
+
result: dict[str, Any] = {
|
|
97
|
+
"$switch": {
|
|
98
|
+
"branches": [
|
|
99
|
+
{
|
|
100
|
+
"case": serialize_value(b.case),
|
|
101
|
+
"then": serialize_value(b.then),
|
|
102
|
+
}
|
|
103
|
+
for b in self.branches
|
|
104
|
+
]
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
if self.default is not None:
|
|
108
|
+
result["$switch"]["default"] = serialize_value(self.default)
|
|
109
|
+
return result
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
__all__ = [
|
|
113
|
+
"CondExpr",
|
|
114
|
+
"IfNullExpr",
|
|
115
|
+
"SwitchBranch",
|
|
116
|
+
"SwitchExpr",
|
|
117
|
+
]
|