Skip to content

Commit 0126c30

Browse files
committed
Added support for subobject indexes.
Makes the 'indexes' MongoMeta option understand dot notation indexes ("foo.bar") for use with DictField, ListField and EmbeddedModelField. Column name substitution has been adapted to recursive into subobjects. Kudos goes to Ellie Frost for the idea and patch. Closes #77.
1 parent 6f9b981 commit 0126c30

File tree

4 files changed

+60
-24
lines changed

4 files changed

+60
-24
lines changed

AUTHORS.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ Past Primary Authors
1313

1414
Contributions by
1515
----------------
16+
* Ellie Frost (https://github.com/stillinbeta)
1617
* Dag Stockstad (https://github.com/dstockstad) -- found tons of bugs in our query generator
1718
* Shane R. Spencer (https://github.com/whardier) -- Website Review
1819
* Sabin Iacob (https://github.com/m0n5t3r)

django_mongodb_engine/creation.py

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@
22
from djangotoolbox.db.base import NonrelDatabaseCreation
33
from .utils import make_index_list
44

5+
56
class DatabaseCreation(NonrelDatabaseCreation):
67
data_types = dict(NonrelDatabaseCreation.data_types, **{
78
'AutoField': 'objectid',
89
'ForeignKey': 'objectid',
910
'OneToOneField': 'objectid',
10-
'RelatedAutoField' : 'objectid',
11+
'RelatedAutoField': 'objectid',
1112
'DecimalField': 'float',
1213
})
1314

@@ -34,6 +35,8 @@ def ensure_index(*args, **kwargs):
3435
self._handle_oldstyle_indexes(ensure_index, meta)
3536

3637
def _handle_newstyle_indexes(self, ensure_index, meta, indexes):
38+
from djangotoolbox.fields import AbstractIterableField, EmbeddedModelField
39+
3740
# Django indexes
3841
for field in meta.local_fields:
3942
if not (field.unique or field.db_index):
@@ -44,21 +47,35 @@ def _handle_newstyle_indexes(self, ensure_index, meta, indexes):
4447

4548
# Django unique_together indexes
4649
indexes = list(indexes)
50+
4751
for fields in getattr(meta, 'unique_together', []):
4852
assert isinstance(fields, (list, tuple))
4953
indexes.append({'fields': make_index_list(fields), 'unique': True})
5054

55+
def get_column_name(field):
56+
opts = meta
57+
parts = field.split('.')
58+
for i, part in enumerate(parts):
59+
field = opts.get_field(part)
60+
parts[i] = field.column
61+
if isinstance(field, AbstractIterableField):
62+
field = field.item_field
63+
if isinstance(field, EmbeddedModelField):
64+
opts = field.embedded_model._meta
65+
else:
66+
break
67+
return '.'.join(parts)
68+
5169
for index in indexes:
5270
if isinstance(index, dict):
5371
kwargs = index.copy()
5472
fields = kwargs.pop('fields')
5573
else:
5674
fields, kwargs = index, {}
57-
fields = [(meta.get_field(name).column, direction)
75+
fields = [(get_column_name(name), direction)
5876
for name, direction in make_index_list(fields)]
5977
ensure_index(fields, **kwargs)
6078

61-
6279
def _handle_oldstyle_indexes(self, ensure_index, meta):
6380
from warnings import warn
6481
warn("'descending_indexes', 'sparse_indexes' and 'index_together' are"

tests/mongodb/models.py

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from django.db import models
2-
from djangotoolbox.fields import RawField, ListField, EmbeddedModelField
2+
from djangotoolbox.fields import RawField, ListField, EmbeddedModelField, DictField
33
from django_mongodb_engine.fields import GridFSField, GridFSString
44
from query.models import Post
55

@@ -40,26 +40,40 @@ class IndexTestModel2(models.Model):
4040
class MongoMeta:
4141
index_together = ['a', ('b', -1)]
4242

43+
class CustomColumnEmbeddedModel(models.Model):
44+
a = models.IntegerField(db_column='a2')
45+
4346
class NewStyleIndexesTestModel(models.Model):
44-
a = models.IntegerField()
45-
b = models.IntegerField(db_column='b2')
46-
c = models.IntegerField(db_index=True)
47-
d = models.IntegerField()
48-
e = models.IntegerField()
49-
f = models.IntegerField(unique=True)
47+
f1 = models.IntegerField()
48+
f2 = models.IntegerField()
49+
f3 = models.IntegerField()
50+
51+
db_index = models.IntegerField(db_index=True)
52+
unique = models.IntegerField(unique=True)
53+
custom_column = models.IntegerField(db_column='custom')
5054
geo = models.IntegerField()
51-
geo2 = models.IntegerField(db_column='geo')
55+
geo_custom_column = models.IntegerField(db_column='geo')
56+
57+
dict1 = DictField()
58+
dict_custom_column = DictField(db_column='dict_custom')
59+
embedded = EmbeddedModelField(CustomColumnEmbeddedModel)
60+
embedded_list = ListField(EmbeddedModelField(CustomColumnEmbeddedModel))
5261

5362
class Meta:
54-
unique_together = [('a', 'b'), ('a', 'd')]
63+
unique_together = [('f2', 'custom_column'), ('f2', 'f3')]
5564

5665
class MongoMeta:
5766
indexes = [
58-
[('e', -1)],
59-
{'fields': 'a', 'sparse': True},
60-
{'fields': [('b', -1), 'd']},
67+
[('f1', -1)],
68+
{'fields': 'f2', 'sparse': True},
69+
{'fields': [('custom_column', -1), 'f3']},
6170
[('geo', '2d')],
62-
{'fields': [('geo2', '2d'), 'a'], 'min': 42, 'max': 21}
71+
{'fields': [('geo_custom_column', '2d'), 'f2'], 'min': 42, 'max': 21},
72+
{'fields': [('dict1.foo', 1)]},
73+
{'fields': [('dict_custom_column.foo', 1)]},
74+
{'fields' :[('embedded.a', 1)]},
75+
{'fields' :[('embedded_list.a', 1)]},
76+
6377
]
6478

6579
class GridFSFieldTestModel(models.Model):

tests/mongodb/tests.py

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -337,15 +337,19 @@ def assertHaveIndex(self, key, **properties):
337337
self.assertEqual(info[index_name], dict(default_properties, **properties))
338338

339339
def test_indexes(self):
340-
self.assertHaveIndex([('c', 1)])
341-
self.assertHaveIndex([('f', 1)], unique=True)
342-
self.assertHaveIndex([('a', 1), ('b2', 1)], unique=True)
343-
self.assertHaveIndex([('a', 1), ('d', 1)], unique=True)
344-
self.assertHaveIndex([('e', -1)])
345-
self.assertHaveIndex([('a', 1)], sparse=True)
346-
self.assertHaveIndex([('b2', -1), ('d', 1)])
340+
self.assertHaveIndex([('db_index', 1)])
341+
self.assertHaveIndex([('unique', 1)], unique=True)
342+
self.assertHaveIndex([('f2', 1), ('custom', 1)], unique=True)
343+
self.assertHaveIndex([('f2', 1), ('f3', 1)], unique=True)
344+
self.assertHaveIndex([('f1', -1)])
345+
self.assertHaveIndex([('f2', 1)], sparse=True)
346+
self.assertHaveIndex([('custom', -1), ('f3', 1)])
347347
self.assertHaveIndex([('geo', '2d')])
348-
self.assertHaveIndex([('geo', '2d'), ('a', 1)], min=42, max=21)
348+
self.assertHaveIndex([('geo', '2d'), ('f2', 1)], min=42, max=21)
349+
self.assertHaveIndex([('dict1.foo', 1)])
350+
self.assertHaveIndex([('dict_custom.foo', 1)])
351+
self.assertHaveIndex([('embedded.a2', 1)])
352+
self.assertHaveIndex([('embedded_list.a2', 1)])
349353

350354
class GridFSFieldTests(TestCase):
351355
def tearDown(self):

0 commit comments

Comments
 (0)