From bc53dd68308c88cc41bb3fb183c1d41392b40968 Mon Sep 17 00:00:00 2001 From: Matthew Ellison Date: Wed, 19 Nov 2014 15:50:32 -0500 Subject: [PATCH 1/3] Generate Unique Indices for Lists of EmbeddedDocs - Unique indices are now created in the database for EmbeddedDocument fields when the EmbeddedDocument is in a ListField - Closes Issue #358 --- AUTHORS | 1 + mongoengine/base/document.py | 3 +++ tests/document/indexes.py | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 36 insertions(+) diff --git a/AUTHORS b/AUTHORS index d377d177..fb9a1ce5 100644 --- a/AUTHORS +++ b/AUTHORS @@ -215,3 +215,4 @@ that much better: * André Ericson https://github.com/aericson) * Mikhail Moshnogorsky (https://github.com/mikhailmoshnogorsky) * Diego Berrocal (https://github.com/cestdiego) + * Matthew Ellison (https://github.com/mmelliso) diff --git a/mongoengine/base/document.py b/mongoengine/base/document.py index 854ed6b4..7a013021 100644 --- a/mongoengine/base/document.py +++ b/mongoengine/base/document.py @@ -816,6 +816,9 @@ class BaseDocument(object): index = {'fields': fields, 'unique': True, 'sparse': sparse} unique_indexes.append(index) + if field.__class__.__name__ == "ListField": + field = field.field + # Grab any embedded document field unique indexes if (field.__class__.__name__ == "EmbeddedDocumentField" and field.document_type != cls): diff --git a/tests/document/indexes.py b/tests/document/indexes.py index 4103c7ae..4815350f 100644 --- a/tests/document/indexes.py +++ b/tests/document/indexes.py @@ -577,6 +577,38 @@ class IndexesTest(unittest.TestCase): BlogPost.drop_collection() + def test_unique_embedded_document_in_list(self): + """ + Ensure that the uniqueness constraints are applied to fields in + embedded documents, even when the embedded documents in in a + list field. + """ + class SubDocument(EmbeddedDocument): + year = IntField(db_field='yr') + slug = StringField(unique=True) + + class BlogPost(Document): + title = StringField() + subs = ListField(EmbeddedDocumentField(SubDocument)) + + BlogPost.drop_collection() + + post1 = BlogPost( + title='test1', subs=[ + SubDocument(year=2009, slug='conflict'), + SubDocument(year=2009, slug='conflict') + ] + ) + post1.save() + + post2 = BlogPost( + title='test2', subs=[SubDocument(year=2014, slug='conflict')] + ) + + self.assertRaises(NotUniqueError, post2.save) + + BlogPost.drop_collection() + def test_unique_with_embedded_document_and_embedded_unique(self): """Ensure that uniqueness constraints are applied to fields on embedded documents. And work with unique_with as well. From 43af9f3fad06388dd02f3da32e241592fc7d22b4 Mon Sep 17 00:00:00 2001 From: Matthew Ellison Date: Thu, 20 Nov 2014 11:20:04 -0500 Subject: [PATCH 2/3] Update Tests for EmbeddedDocument Unique Indicies --- tests/fields/fields.py | 8 ++++---- tests/queryset/queryset.py | 10 +++++----- tests/test_dereference.py | 17 +++++++++-------- 3 files changed, 18 insertions(+), 17 deletions(-) diff --git a/tests/fields/fields.py b/tests/fields/fields.py index 1079b235..d7edea37 100644 --- a/tests/fields/fields.py +++ b/tests/fields/fields.py @@ -1974,14 +1974,14 @@ class FieldTest(unittest.TestCase): def test_recursive_embedding(self): """Ensure that EmbeddedDocumentFields can contain their own documents. """ - class Tree(Document): - name = StringField() - children = ListField(EmbeddedDocumentField('TreeNode')) - class TreeNode(EmbeddedDocument): name = StringField() children = ListField(EmbeddedDocumentField('self')) + class Tree(Document): + name = StringField() + children = ListField(EmbeddedDocumentField('TreeNode')) + Tree.drop_collection() tree = Tree(name="Tree") diff --git a/tests/queryset/queryset.py b/tests/queryset/queryset.py index 40d010c6..703728fe 100644 --- a/tests/queryset/queryset.py +++ b/tests/queryset/queryset.py @@ -512,16 +512,16 @@ class QuerySetTest(unittest.TestCase): def test_updates_can_have_match_operators(self): - class Post(Document): - title = StringField(required=True) - tags = ListField(StringField()) - comments = ListField(EmbeddedDocumentField("Comment")) - class Comment(EmbeddedDocument): content = StringField() name = StringField(max_length=120) vote = IntField() + class Post(Document): + title = StringField(required=True) + tags = ListField(StringField()) + comments = ListField(EmbeddedDocumentField("Comment")) + Post.drop_collection() comm1 = Comment(content="very funny indeed", name="John S", vote=1) diff --git a/tests/test_dereference.py b/tests/test_dereference.py index c37ada59..85588558 100644 --- a/tests/test_dereference.py +++ b/tests/test_dereference.py @@ -318,6 +318,10 @@ class FieldTest(unittest.TestCase): def test_circular_reference(self): """Ensure you can handle circular references """ + class Relation(EmbeddedDocument): + name = StringField() + person = ReferenceField('Person') + class Person(Document): name = StringField() relations = ListField(EmbeddedDocumentField('Relation')) @@ -325,10 +329,6 @@ class FieldTest(unittest.TestCase): def __repr__(self): return "" % self.name - class Relation(EmbeddedDocument): - name = StringField() - person = ReferenceField('Person') - Person.drop_collection() mother = Person(name="Mother") daughter = Person(name="Daughter") @@ -1220,14 +1220,15 @@ class FieldTest(unittest.TestCase): self.assertEqual(page.tags[0], page.posts[0].tags[0]) def test_select_related_follows_embedded_referencefields(self): - class Playlist(Document): - items = ListField(EmbeddedDocumentField("PlaylistItem")) + + class Song(Document): + title = StringField() class PlaylistItem(EmbeddedDocument): song = ReferenceField("Song") - class Song(Document): - title = StringField() + class Playlist(Document): + items = ListField(EmbeddedDocumentField("PlaylistItem")) Playlist.drop_collection() Song.drop_collection() From d70b7d41e816d5fde6d3b2e2a3696235a2e0993e Mon Sep 17 00:00:00 2001 From: Matthew Ellison Date: Fri, 21 Nov 2014 07:29:50 -0500 Subject: [PATCH 3/3] Update to Changelog to include Fix for #358 --- docs/changelog.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/changelog.rst b/docs/changelog.rst index 35b94b1e..0ccb8491 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -5,6 +5,7 @@ Changelog Changes in 0.9.X - DEV ====================== +- Generate Unique Indicies for Lists of EmbeddedDocuments #358 - Sparse fields #515 - write_concern not in params of Collection#remove #801 - Better BaseDocument equality check when not saved #798