1
1
import difflib
2
2
3
3
from django .core .exceptions import FieldDoesNotExist
4
+ from django .db import models
4
5
from django .db .models import Field
6
+ from django .db .models .expressions import Col
5
7
from django .db .models .lookups import Transform
6
8
7
9
from .. import forms
8
10
from ..query_utils import process_lhs , process_rhs
9
11
from . import EmbeddedModelField
10
12
from .array import ArrayField
11
13
from .embedded_model import EMFExact
12
- from .json import build_json_mql_path
13
14
14
15
15
16
class EmbeddedModelArrayField (ArrayField ):
@@ -63,18 +64,29 @@ def get_transform(self, name):
63
64
@EmbeddedModelArrayField .register_lookup
64
65
class EMFArrayExact (EMFExact ):
65
66
def as_mql (self , compiler , connection ):
66
- mql , key_transforms , json_key_transforms = self .lhs .preprocess_lhs (compiler , connection )
67
- # TODO, maybe a new flow of transform query must be build
68
- # this part must merge the two part of the transform train.
67
+ lhs_mql = process_lhs (self , compiler , connection )
69
68
value = process_rhs (self , compiler , connection )
70
- transforms = build_json_mql_path ("$$this" , key_transforms )
71
- return {
72
- "$reduce" : {
73
- "input" : mql ,
74
- "initialValue" : False ,
75
- "in" : {"$or" : ["$$value" , {"$eq" : [f"$$this.{ transforms } " , value ]}]},
69
+ if isinstance (self .lhs , Col | KeyTransform ):
70
+ if isinstance (value , models .Model ):
71
+ value , emf_data = self .model_to_dict (value )
72
+ # Get conditions for any nested EmbeddedModelFields.
73
+ conditions = self .get_conditions ({"$$item" : (value , emf_data )})
74
+ return {
75
+ "$anyElementTrue" : {
76
+ "$map" : {"input" : lhs_mql , "as" : "item" , "in" : {"$and" : conditions }}
77
+ }
78
+ }
79
+ lhs_mql = process_lhs (self .lhs , compiler , connection )
80
+ return {
81
+ "$anyElementTrue" : {
82
+ "$map" : {
83
+ "input" : lhs_mql ,
84
+ "as" : "item" ,
85
+ "in" : {"$eq" : [f"$$item.{ self .lhs .key_name } " , value ]},
86
+ }
87
+ }
76
88
}
77
- }
89
+ return connection . mongo_operators [ self . lookup_name ]( lhs_mql , value )
78
90
79
91
80
92
class KeyTransform (Transform ):
@@ -85,7 +97,7 @@ def __init__(self, key_name, ref_field, *args, **kwargs):
85
97
self .ref_field = ref_field
86
98
87
99
def get_lookup (self , name ):
88
- return self .ref_field .get_lookup (name )
100
+ return self .output_field .get_lookup (name )
89
101
90
102
def get_transform (self , name ):
91
103
"""
@@ -107,11 +119,12 @@ def get_transform(self, name):
107
119
)
108
120
109
121
def as_mql (self , compiler , connection ):
110
- return process_lhs (self , compiler , connection )
122
+ lhs_mql = process_lhs (self , compiler , connection )
123
+ return f"{ lhs_mql } .{ self .key_name } "
111
124
112
125
@property
113
126
def output_field (self ):
114
- return self .ref_field
127
+ return EmbeddedModelArrayField ( self .ref_field )
115
128
116
129
117
130
class KeyTransformFactory :
0 commit comments