Skip to content

Commit feee2de

Browse files
committed
Simple filtering approach
1 parent 89ea845 commit feee2de

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):
@@ -47,17 +53,71 @@ def formfield(self, **kwargs):
4753
)
4854

4955
def get_transform(self, name):
50-
# TODO: ...
51-
return self.base_field.get_transform(name)
52-
# Copied from EmbedddedModelField -- customize?
53-
# transform = super().get_transform(name)
54-
# if transform:
55-
# return transform
56-
# field = self.embedded_model._meta.get_field(name)
57-
# return KeyTransformFactory(name, field)
56+
transform = super().get_transform(name)
57+
if transform:
58+
return transform
59+
field = self.base_field.embedded_model._meta.get_field(name)
60+
return KeyTransformFactory(name, field)
5861

5962

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