Skip to content

Commit b7278d5

Browse files
committed
[WIP] Implemented OtherNested (name TBD)
Proof of concept only
1 parent 1cb17a0 commit b7278d5

File tree

3 files changed

+58
-6
lines changed

3 files changed

+58
-6
lines changed

elasticsearch_dsl/document.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,13 @@ def init(self, index=None, using=None):
9595
def refresh(self, index=None, using=None):
9696
self.mapping.update_from_es(index or self.index, using=using or self.using)
9797

98+
@add_metaclass(DocTypeMeta)
99+
class InnerDoc(ObjectBase):
100+
"""
101+
Common class for inner documents like Object or Nested
102+
"""
103+
pass
104+
98105

99106
@add_metaclass(DocTypeMeta)
100107
class DocType(ObjectBase):

elasticsearch_dsl/field.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,50 @@ def __init__(self, mapping, **kwargs):
105105
super(AttrDict, self).__setattr__('_doc_type', type('Meta', (), {'mapping': mapping}))
106106
super(InnerObjectWrapper, self).__init__(**kwargs)
107107

108+
class OtherNested(Field):
109+
_coerce = True
110+
111+
def __init__(self, doc_class, **kwargs):
112+
self._doc_class = doc_class
113+
kwargs.setdefault('multi', True)
114+
super(OtherNested, self).__init__(**kwargs)
115+
116+
def to_dict(self):
117+
d = self._doc_class._doc_type.mapping.to_dict()
118+
_, d = d.popitem()
119+
d["type"] = "nested"
120+
return d
121+
122+
def _collect_fields(self):
123+
return self._doc_class._doc_type.mapping.properties._collect_fields()
124+
125+
def _deserialize(self, data):
126+
if data is None:
127+
return None
128+
# don't wrap already wrapped data
129+
if isinstance(data, self._doc_class):
130+
return data
131+
132+
if isinstance(data, AttrDict):
133+
data = data._d_
134+
135+
return self._doc_class(**data)
136+
137+
def _serialize(self, data):
138+
if data is None:
139+
return None
140+
return data.to_dict()
141+
142+
def clean(self, data):
143+
data = super(OtherNested, self).clean(data)
144+
if data is None:
145+
return None
146+
if isinstance(data, (list, AttrList)):
147+
for d in data:
148+
d.full_clean()
149+
else:
150+
data.full_clean()
151+
return data
108152

109153
class InnerObject(object):
110154
" Common functionality for nested and object fields. "

test_elasticsearch_dsl/test_document.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,12 @@ class MyDoc2(document.DocType):
3030
class MyMultiSubDoc(MyDoc2, MySubDoc):
3131
pass
3232

33+
class Comment(document.InnerDoc):
34+
title = field.Text()
35+
tags = field.Keyword(multi=True)
36+
3337
class DocWithNested(document.DocType):
34-
comments = field.Nested(
35-
properties={
36-
'title': field.Text(),
37-
'tags': field.Keyword(multi=True)
38-
}
39-
)
38+
comments = field.OtherNested(Comment)
4039

4140
class SimpleCommit(document.DocType):
4241
files = field.Text(multi=True)
@@ -240,8 +239,10 @@ def test_nested_can_be_assigned_to():
240239
d2 = DocWithNested()
241240

242241
d2.comments = d1.comments
242+
assert isinstance(d1.comments[0], Comment)
243243
assert d2.comments == [{'title': 'First!'}]
244244
assert {'comments': [{'title': 'First!'}]} == d2.to_dict()
245+
assert isinstance(d2.comments[0], Comment)
245246

246247
def test_nested_can_be_none():
247248
d = DocWithNested(comments=None, title='Hello World!')

0 commit comments

Comments
 (0)