Skip to content

Commit 6183c7e

Browse files
committed
Simple filtering approach
1 parent 821be58 commit 6183c7e

File tree

3 files changed

+73
-18
lines changed

3 files changed

+73
-18
lines changed

django_mongodb_backend/fields/embedded_model.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -186,8 +186,9 @@ def as_mql(self, compiler, connection):
186186
key_transforms.insert(0, previous.key_name)
187187
previous = previous.lhs
188188
mql = previous.as_mql(compiler, connection)
189-
transforms = ".".join(key_transforms)
190-
return f"{mql}.{transforms}"
189+
for key in key_transforms:
190+
mql = {"$getField": {"input": mql, "field": key}}
191+
return mql
191192

192193
@property
193194
def output_field(self):

django_mongodb_backend/fields/embedded_model_array.py

Lines changed: 70 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
1+
import difflib
2+
3+
from django.core.exceptions import FieldDoesNotExist
14
from django.db.models import Field
5+
from django.db.models.lookups import Transform
26

37
from .. import forms
8+
from ..query_utils import process_lhs, process_rhs
49
from . import EmbeddedModelField
510
from .array import ArrayField
611
from .embedded_model import EMFExact
12+
from .json import build_json_mql_path
713

814

915
class EmbeddedModelArrayField(ArrayField):
@@ -50,17 +56,71 @@ def formfield(self, **kwargs):
5056
)
5157

5258
def get_transform(self, name):
53-
# TODO: ...
54-
return self.base_field.get_transform(name)
55-
# Copied from EmbedddedModelField -- customize?
56-
# transform = super().get_transform(name)
57-
# if transform:
58-
# return transform
59-
# field = self.embedded_model._meta.get_field(name)
60-
# return KeyTransformFactory(name, field)
59+
transform = super().get_transform(name)
60+
if transform:
61+
return transform
62+
field = self.base_field.embedded_model._meta.get_field(name)
63+
return KeyTransformFactory(name, field)
6164

6265

6366
@EmbeddedModelArrayField.register_lookup
6467
class EMFArrayExact(EMFExact):
65-
# TODO
66-
pass
68+
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.
72+
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]}]},
79+
}
80+
}
81+
82+
83+
class KeyTransform(Transform):
84+
# it should be different class than EMF keytransform even most of the methods are equal.
85+
def __init__(self, key_name, ref_field, *args, **kwargs):
86+
super().__init__(*args, **kwargs)
87+
self.key_name = str(key_name)
88+
self.ref_field = ref_field
89+
90+
def get_lookup(self, name):
91+
return self.ref_field.get_lookup(name)
92+
93+
def get_transform(self, name):
94+
"""
95+
Validate that `name` is either a field of an embedded model or a
96+
lookup on an embedded model's field.
97+
"""
98+
if transform := self.ref_field.get_transform(name):
99+
return transform
100+
suggested_lookups = difflib.get_close_matches(name, self.ref_field.get_lookups())
101+
if suggested_lookups:
102+
suggested_lookups = " or ".join(suggested_lookups)
103+
suggestion = f", perhaps you meant {suggested_lookups}?"
104+
else:
105+
suggestion = "."
106+
raise FieldDoesNotExist(
107+
f"Unsupported lookup '{name}' for "
108+
f"{self.ref_field.__class__.__name__} '{self.ref_field.name}'"
109+
f"{suggestion}"
110+
)
111+
112+
def as_mql(self, compiler, connection):
113+
return process_lhs(self, compiler, connection)
114+
115+
@property
116+
def output_field(self):
117+
return self.ref_field
118+
119+
120+
class KeyTransformFactory:
121+
def __init__(self, key_name, ref_field):
122+
self.key_name = key_name
123+
self.ref_field = ref_field
124+
125+
def __call__(self, *args, **kwargs):
126+
return KeyTransform(self.key_name, self.ref_field, *args, **kwargs)

tests/model_fields_/test_embedded_model.py

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,11 @@
1717
from django_mongodb_backend.fields import EmbeddedModelField
1818
from django_mongodb_backend.models import EmbeddedModel
1919

20-
2120
from .models import (
22-
A,
2321
Address,
2422
Author,
25-
B,
2623
Book,
27-
C,
28-
D,
2924
Data,
30-
E,
3125
Holder,
3226
Library,
3327
Movie,

0 commit comments

Comments
 (0)