Skip to content

Commit 51de1cc

Browse files
committed
Simple filtering approach
1 parent 1606bdb commit 51de1cc

File tree

2 files changed

+74
-12
lines changed

2 files changed

+74
-12
lines changed

django_mongodb_backend/fields/embedded_model.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -245,8 +245,9 @@ def as_mql(self, compiler, connection):
245245
key_transforms.insert(0, previous.key_name)
246246
previous = previous.lhs
247247
mql = previous.as_mql(compiler, connection)
248-
transforms = ".".join(key_transforms)
249-
return f"{mql}.{transforms}"
248+
for key in key_transforms:
249+
mql = {"$getField": {"input": mql, "field": key}}
250+
return mql
250251

251252
@property
252253
def output_field(self):

django_mongodb_backend/fields/embedded_model_array.py

Lines changed: 71 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,14 @@
1+
import difflib
2+
3+
from django.core.exceptions import FieldDoesNotExist
4+
from django.db.models.lookups import Transform
5+
16
from ..forms import EmbeddedModelArrayFormField
7+
from ..query_utils import process_lhs, process_rhs
28
from . import EmbeddedModelField
39
from .array import ArrayField
410
from .embedded_model import EMFExact
11+
from .json import build_json_mql_path
512

613

714
class EmbeddedModelArrayField(ArrayField):
@@ -38,17 +45,71 @@ def formfield(self, **kwargs):
3845
)
3946

4047
def get_transform(self, name):
41-
# TODO: ...
42-
return self.base_field.get_transform(name)
43-
# Copied from EmbedddedModelField -- customize?
44-
# transform = super().get_transform(name)
45-
# if transform:
46-
# return transform
47-
# field = self.embedded_model._meta.get_field(name)
48-
# return KeyTransformFactory(name, field)
48+
transform = super().get_transform(name)
49+
if transform:
50+
return transform
51+
field = self.base_field.embedded_model._meta.get_field(name)
52+
return KeyTransformFactory(name, field)
4953

5054

5155
@EmbeddedModelArrayField.register_lookup
5256
class EMFArrayExact(EMFExact):
53-
# TODO
54-
pass
57+
def as_mql(self, compiler, connection):
58+
mql, key_transforms, json_key_transforms = self.lhs.preprocess_lhs(compiler, connection)
59+
# TODO, maybe a new flow of transform query must be build
60+
# this part must merge the two part of the transform train.
61+
value = process_rhs(self, compiler, connection)
62+
transforms = build_json_mql_path("$$this", key_transforms)
63+
return {
64+
"$reduce": {
65+
"input": mql,
66+
"initialValue": False,
67+
"in": {"$or": ["$$value", {"$eq": [f"$$this.{transforms}", value]}]},
68+
}
69+
}
70+
71+
72+
class KeyTransform(Transform):
73+
# it should be different class than EMF keytransform even most of the methods are equal.
74+
def __init__(self, key_name, ref_field, *args, **kwargs):
75+
super().__init__(*args, **kwargs)
76+
self.key_name = str(key_name)
77+
self.ref_field = ref_field
78+
79+
def get_lookup(self, name):
80+
return self.ref_field.get_lookup(name)
81+
82+
def get_transform(self, name):
83+
"""
84+
Validate that `name` is either a field of an embedded model or a
85+
lookup on an embedded model's field.
86+
"""
87+
if transform := self.ref_field.get_transform(name):
88+
return transform
89+
suggested_lookups = difflib.get_close_matches(name, self.ref_field.get_lookups())
90+
if suggested_lookups:
91+
suggested_lookups = " or ".join(suggested_lookups)
92+
suggestion = f", perhaps you meant {suggested_lookups}?"
93+
else:
94+
suggestion = "."
95+
raise FieldDoesNotExist(
96+
f"Unsupported lookup '{name}' for "
97+
f"{self.ref_field.__class__.__name__} '{self.ref_field.name}'"
98+
f"{suggestion}"
99+
)
100+
101+
def as_mql(self, compiler, connection):
102+
return process_lhs(self, compiler, connection)
103+
104+
@property
105+
def output_field(self):
106+
return self.ref_field
107+
108+
109+
class KeyTransformFactory:
110+
def __init__(self, key_name, ref_field):
111+
self.key_name = key_name
112+
self.ref_field = ref_field
113+
114+
def __call__(self, *args, **kwargs):
115+
return KeyTransform(self.key_name, self.ref_field, *args, **kwargs)

0 commit comments

Comments
 (0)