Repository: MongoEngine/mongoengine

Issue:
Sparse fields?
I have a field in my document schema that is `unique=True` but not meant to be required. When I try to save the document though, mongoengine throws `ValidationError (Field is required)`. Apparently the solution is setting the field to be `sparse: true` (as per [this](http://stackoverflow.com/a/9693138/818492)) such that two null values count as duplicate values. Is this implemented in mongoengine?



Discussion:
It is but you have to manually state your index: See http://docs.mongoengine.org/en/latest/guide/defining-documents.html?highlight=sparse#indexes

Add a sparse value to Field definitions.


Resolving patch:
diff --git a/mongoengine/base/document.py b/mongoengine/base/document.py
--- a/mongoengine/base/document.py
+++ b/mongoengine/base/document.py
@@ -786,10 +786,9 @@ def _unique_with_indexes(cls, namespace=""):
         """
         unique_indexes = []
         for field_name, field in cls._fields.items():
-            sparse = False
+            sparse = field.sparse
             # Generate a list of indexes needed by uniqueness constraints
             if field.unique:
-                field.required = True
                 unique_fields = [field.db_field]
 
                 # Add any unique_with fields to the back of the index spec
diff --git a/mongoengine/base/fields.py b/mongoengine/base/fields.py
--- a/mongoengine/base/fields.py
+++ b/mongoengine/base/fields.py
@@ -37,7 +37,7 @@ class BaseField(object):
     def __init__(self, db_field=None, name=None, required=False, default=None,
                  unique=False, unique_with=None, primary_key=False,
                  validation=None, choices=None, verbose_name=None,
-                 help_text=None, null=False):
+                 help_text=None, null=False, sparse=False):
         """
         :param db_field: The database field to store this field in
             (defaults to the name of the field)
@@ -62,6 +62,8 @@ def __init__(self, db_field=None, name=None, required=False, default=None,
             used when generating model forms from the document model.
         :param null: (optional) Is the field value can be null. If no and there is a default value
             then the default value is set
+        :param sparse: (optional) `sparse=True` combined with `unique=True` and `required=False`
+            means that uniqueness won't be enforced for `None` values
         """
         self.db_field = (db_field or name) if not primary_key else '_id'
 
@@ -78,6 +80,7 @@ def __init__(self, db_field=None, name=None, required=False, default=None,
         self.verbose_name = verbose_name
         self.help_text = help_text
         self.null = null
+        self.sparse = sparse
 
         # Adjust the appropriate creation counter, and save our local copy.
         if self.db_field == '_id':


Test patch:
diff --git a/tests/fields/fields.py b/tests/fields/fields.py
--- a/tests/fields/fields.py
+++ b/tests/fields/fields.py
@@ -3057,6 +3057,15 @@ class Human(Mammal):
         self.assertEquals(Animal.objects(_cls__in=["Animal.Mammal.Dog", "Animal.Fish"]).count(), 2)
         self.assertEquals(Animal.objects(_cls__in=["Animal.Fish.Guppy"]).count(), 0)
 
+    def test_sparse_field(self):
+        class Doc(Document):
+            name = StringField(required=False, unique=True, sparse=True)
+        try:
+            Doc().save()
+            Doc().save()
+        except Exception:
+            self.fail()
+
 
 if __name__ == '__main__':
     unittest.main()