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 ):
@@ -66,18 +67,29 @@ def get_transform(self, name):
66
67
@EmbeddedModelArrayField .register_lookup
67
68
class EMFArrayExact (EMFExact ):
68
69
def as_mql (self , compiler , connection ):
69
- mql , key_transforms , json_key_transforms = self .lhs .preprocess_lhs (compiler , connection )
70
- # TODO, maybe a new flow of transform query must be build
71
- # this part must merge the two part of the transform train.
70
+ lhs_mql = process_lhs (self , compiler , connection )
72
71
value = process_rhs (self , compiler , connection )
73
- transforms = build_json_mql_path ("$$this" , key_transforms )
74
- return {
75
- "$reduce" : {
76
- "input" : mql ,
77
- "initialValue" : False ,
78
- "in" : {"$or" : ["$$value" , {"$eq" : [f"$$this.{ transforms } " , value ]}]},
72
+ if isinstance (self .lhs , Col | KeyTransform ):
73
+ if isinstance (value , models .Model ):
74
+ value , emf_data = self .model_to_dict (value )
75
+ # Get conditions for any nested EmbeddedModelFields.
76
+ conditions = self .get_conditions ({"$$item" : (value , emf_data )})
77
+ return {
78
+ "$anyElementTrue" : {
79
+ "$map" : {"input" : lhs_mql , "as" : "item" , "in" : {"$and" : conditions }}
80
+ }
81
+ }
82
+ lhs_mql = process_lhs (self .lhs , compiler , connection )
83
+ return {
84
+ "$anyElementTrue" : {
85
+ "$map" : {
86
+ "input" : lhs_mql ,
87
+ "as" : "item" ,
88
+ "in" : {"$eq" : [f"$$item.{ self .lhs .key_name } " , value ]},
89
+ }
90
+ }
79
91
}
80
- }
92
+ return connection . mongo_operators [ self . lookup_name ]( lhs_mql , value )
81
93
82
94
83
95
class KeyTransform (Transform ):
@@ -88,7 +100,7 @@ def __init__(self, key_name, ref_field, *args, **kwargs):
88
100
self .ref_field = ref_field
89
101
90
102
def get_lookup (self , name ):
91
- return self .ref_field .get_lookup (name )
103
+ return self .output_field .get_lookup (name )
92
104
93
105
def get_transform (self , name ):
94
106
"""
@@ -110,11 +122,12 @@ def get_transform(self, name):
110
122
)
111
123
112
124
def as_mql (self , compiler , connection ):
113
- return process_lhs (self , compiler , connection )
125
+ lhs_mql = process_lhs (self , compiler , connection )
126
+ return f"{ lhs_mql } .{ self .key_name } "
114
127
115
128
@property
116
129
def output_field (self ):
117
- return self .ref_field
130
+ return EmbeddedModelArrayField ( self .ref_field )
118
131
119
132
120
133
class KeyTransformFactory :
0 commit comments