@@ -64,16 +64,9 @@ def from_db_value(self, value, expression, connection):
64
64
65
65
def json_process_rhs (node , compiler , connection ):
66
66
_ , value = node .process_rhs (compiler , connection )
67
-
68
67
lookup_name = node .lookup_name
69
68
if lookup_name not in ("in" , "range" ):
70
69
value = value [0 ] if len (value ) > 0 else []
71
- else :
72
- result_value = []
73
- for ind , elem in enumerate (node .rhs ):
74
- item = f"${ value [ind ]} " if isinstance (elem , KeyTransform ) else value [ind ]
75
- result_value .append (item )
76
- value = result_value
77
70
78
71
return value
79
72
@@ -97,35 +90,31 @@ def contained_by(self, compiler, connection): # noqa: ARG001
97
90
98
91
99
92
def json_exact (self , compiler , connection ):
100
- lhs_mql = process_lhs (self , compiler , connection )
93
+ lhs_mql = process_lhs (self , compiler , connection , bare_column_ref = True )
101
94
rhs_mql = json_process_rhs (self , compiler , connection )
102
95
if rhs_mql == "null" :
103
96
return {"$or" : [{lhs_mql : {"$eq" : None }}, {lhs_mql : {"$exists" : False }}]}
104
- # return {lhs_mql: {"$eq": None, "$exists": True}}
105
- # return key_transform_isnull(self, compiler, connection)
106
97
return {lhs_mql : {"$eq" : rhs_mql , "$exists" : True }}
107
98
108
99
109
100
def key_transform_isnull (self , compiler , connection ):
110
- lhs_mql = process_lhs (self , compiler , connection )
101
+ lhs_mql = process_lhs (self , compiler , connection , bare_column_ref = True )
111
102
rhs_mql = json_process_rhs (self , compiler , connection )
112
- # if rhs_mql is False:
113
- # return {lhs_mql: {"$neq": None}}
114
- # return {"$or": [{lhs_mql: {"$eq": None}}, {lhs_mql: {"$exists": False}}]}
115
103
116
104
# https://code.djangoproject.com/ticket/32252
117
105
return {lhs_mql : {"$exists" : not rhs_mql }}
118
106
119
107
120
108
def key_transform_in (self , compiler , connection ):
121
- lhs_mql = process_lhs (self , compiler , connection )
109
+ lhs_mql = key_transform_agg (self .lhs , compiler , connection )
110
+ bare_lhs_mql = process_lhs (self , compiler , connection , bare_column_ref = True )
122
111
value = json_process_rhs (self , compiler , connection )
123
- rhs_mql = connection .operators [self .lookup_name ](value )
124
- return {"$expr" : { lhs_mql : rhs_mql }}
112
+ expr = connection .mongo_aggregations [self .lookup_name ](lhs_mql , value )
113
+ return {"$expr" : expr , bare_lhs_mql : { "$exists" : True }}
125
114
126
115
127
116
def has_key_lookup (self , compiler , connection ):
128
- lhs = process_lhs (self , compiler , connection )
117
+ lhs = process_lhs (self , compiler , connection , bare_column_ref = True )
129
118
rhs = self .rhs
130
119
if not isinstance (rhs , (list | tuple )):
131
120
rhs = [rhs ]
@@ -148,10 +137,34 @@ def has_key_lookup(self, compiler, connection):
148
137
return {self .mongo_operator : keys }
149
138
150
139
140
+ def key_transform_agg (self , compiler , connection ):
141
+ key_transforms = [self .key_name ]
142
+ previous = self .lhs
143
+ while isinstance (previous , KeyTransform ):
144
+ key_transforms .insert (0 , previous .key_name )
145
+ previous = previous .lhs
146
+ lhs_mql = previous .as_mql (compiler , connection )
147
+ result = f"{ lhs_mql } "
148
+ for key in key_transforms :
149
+ get_field = {"$getField" : {"input" : result , "field" : key }}
150
+ if key .isdigit ():
151
+ result = {
152
+ "$cond" : {
153
+ "if" : {"$isArray" : result },
154
+ "then" : {"$arrayElemAt" : [result , int (key )]},
155
+ "else" : get_field ,
156
+ }
157
+ }
158
+ else :
159
+ result = get_field
160
+ return result
161
+
162
+
151
163
def load_fields ():
152
164
JSONField .from_db_value = from_db_value
153
165
DataContains .as_mql = data_contains
154
166
KeyTransform .as_mql = key_transform
167
+ KeyTransform .as_mql_agg = key_transform_agg
155
168
JSONExact .as_mql = json_exact
156
169
ContainedBy .as_mql = contained_by
157
170
HasKeyLookup .as_mql = has_key_lookup
0 commit comments