8
8
from fastapi_pagination .default import Params as BaseParams
9
9
from fief_client import FiefUserInfo
10
10
from pydantic import BaseModel
11
+ from pydantic .fields import ModelField
11
12
12
13
from opensensor .collections import (
13
14
CO2 ,
@@ -197,9 +198,19 @@ def get_nested_fields(model: Type[BaseModel]) -> Dict[str, Type[BaseModel]]:
197
198
return nested_fields
198
199
199
200
201
+ def is_list_of_models (field : ModelField ) -> bool :
202
+ if field .shape != 2 : # 2 represents a list shape in Pydantic
203
+ return False
204
+ args = field .sub_fields [0 ].type_ .__args__
205
+ return args and is_pydantic_model (args [0 ])
206
+
207
+
208
+ def get_list_item_type (field : ModelField ) -> Type [BaseModel ]:
209
+ return field .sub_fields [0 ].type_ .__args__ [0 ]
210
+
211
+
200
212
def create_nested_pipeline (model : Type [BaseModel ], prefix = "" ):
201
213
logger .debug (f"Creating nested pipeline for model: { model .__name__ } , prefix: { prefix } " )
202
- nested_fields = get_nested_fields (model )
203
214
match_conditions = {}
204
215
pipeline = {
205
216
"timestamp" : "$timestamp" ,
@@ -218,24 +229,13 @@ def create_nested_pipeline(model: Type[BaseModel], prefix=""):
218
229
unit_field_name = f"{ prefix } { mongo_field } _unit"
219
230
pipeline ["unit" ] = f"${ unit_field_name } "
220
231
match_conditions [unit_field_name ] = {"$exists" : True }
221
- elif field_name in nested_fields :
222
- nested_type = nested_fields [field_name ]
223
- if get_origin (field .type_ ) is List :
224
- # Handle array of nested objects
225
- nested_pipeline , nested_match = create_nested_pipeline (nested_type , "" )
226
- pipeline [field_name ] = {
227
- "$map" : {
228
- "input" : f"${ full_mongo_field_name } " ,
229
- "as" : "item" ,
230
- "in" : nested_pipeline ,
231
- }
232
- }
233
- match_conditions [full_mongo_field_name ] = {"$exists" : True , "$ne" : []}
234
- else :
235
- # Handle nested object
236
- nested_pipeline , nested_match = create_nested_pipeline (nested_type , "" )
237
- pipeline [field_name ] = nested_pipeline
238
- match_conditions .update ({f"{ field_name } .{ k } " : v for k , v in nested_match .items ()})
232
+ elif is_list_of_models (field ):
233
+ item_model = get_list_item_type (field )
234
+ nested_pipeline , nested_match = create_nested_pipeline (item_model , "" )
235
+ pipeline [field_name ] = {
236
+ "$map" : {"input" : f"${ full_mongo_field_name } " , "as" : "item" , "in" : nested_pipeline }
237
+ }
238
+ match_conditions [full_mongo_field_name ] = {"$exists" : True , "$ne" : []}
239
239
else :
240
240
# Handle simple field
241
241
pipeline [field_name ] = f"${ full_mongo_field_name } "
0 commit comments