parent
f80f0b416f
commit
ca8b58d66d
@ -4,6 +4,7 @@ Changelog
|
|||||||
|
|
||||||
Changes in 0.6.X
|
Changes in 0.6.X
|
||||||
================
|
================
|
||||||
|
- Fixed indexing on '_id' or 'pk' or 'id'
|
||||||
- Invalid data from the DB now raises a InvalidDocumentError
|
- Invalid data from the DB now raises a InvalidDocumentError
|
||||||
- Cleaned up the Validation Error - docs and code
|
- Cleaned up the Validation Error - docs and code
|
||||||
- Added meta `auto_create_index` so you can disable index creation
|
- Added meta `auto_create_index` so you can disable index creation
|
||||||
|
@ -394,61 +394,6 @@ class QuerySet(object):
|
|||||||
unique=index_spec.get('unique', False))
|
unique=index_spec.get('unique', False))
|
||||||
return self
|
return self
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def _build_index_spec(cls, doc_cls, spec):
|
|
||||||
"""Build a PyMongo index spec from a MongoEngine index spec.
|
|
||||||
"""
|
|
||||||
if isinstance(spec, basestring):
|
|
||||||
spec = {'fields': [spec]}
|
|
||||||
if isinstance(spec, (list, tuple)):
|
|
||||||
spec = {'fields': spec}
|
|
||||||
|
|
||||||
index_list = []
|
|
||||||
use_types = doc_cls._meta.get('allow_inheritance', True)
|
|
||||||
for key in spec['fields']:
|
|
||||||
# Get ASCENDING direction from +, DESCENDING from -, and GEO2D from *
|
|
||||||
direction = pymongo.ASCENDING
|
|
||||||
if key.startswith("-"):
|
|
||||||
direction = pymongo.DESCENDING
|
|
||||||
elif key.startswith("*"):
|
|
||||||
direction = pymongo.GEO2D
|
|
||||||
if key.startswith(("+", "-", "*")):
|
|
||||||
key = key[1:]
|
|
||||||
|
|
||||||
# Use real field name, do it manually because we need field
|
|
||||||
# objects for the next part (list field checking)
|
|
||||||
parts = key.split('.')
|
|
||||||
fields = QuerySet._lookup_field(doc_cls, parts)
|
|
||||||
parts = [field.db_field for field in fields]
|
|
||||||
key = '.'.join(parts)
|
|
||||||
index_list.append((key, direction))
|
|
||||||
|
|
||||||
# Check if a list field is being used, don't use _types if it is
|
|
||||||
if use_types and not all(f._index_with_types for f in fields):
|
|
||||||
use_types = False
|
|
||||||
|
|
||||||
# If _types is being used, prepend it to every specified index
|
|
||||||
index_types = doc_cls._meta.get('index_types', True)
|
|
||||||
allow_inheritance = doc_cls._meta.get('allow_inheritance')
|
|
||||||
if spec.get('types', index_types) and allow_inheritance and use_types and direction is not pymongo.GEO2D:
|
|
||||||
index_list.insert(0, ('_types', 1))
|
|
||||||
|
|
||||||
spec['fields'] = index_list
|
|
||||||
|
|
||||||
if spec.get('sparse', False) and len(spec['fields']) > 1:
|
|
||||||
raise ValueError(
|
|
||||||
'Sparse indexes can only have one field in them. '
|
|
||||||
'See https://jira.mongodb.org/browse/SERVER-2193')
|
|
||||||
|
|
||||||
return spec
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def _reset_already_indexed(cls, document=None):
|
|
||||||
"""Helper to reset already indexed, can be useful for testing purposes"""
|
|
||||||
if document:
|
|
||||||
cls.__already_indexed.discard(document)
|
|
||||||
cls.__already_indexed.clear()
|
|
||||||
|
|
||||||
def __call__(self, q_obj=None, class_check=True, slave_okay=False, **query):
|
def __call__(self, q_obj=None, class_check=True, slave_okay=False, **query):
|
||||||
"""Filter the selected documents by calling the
|
"""Filter the selected documents by calling the
|
||||||
:class:`~mongoengine.queryset.QuerySet` with a query.
|
:class:`~mongoengine.queryset.QuerySet` with a query.
|
||||||
@ -534,6 +479,62 @@ class QuerySet(object):
|
|||||||
self._collection.ensure_index(index_spec,
|
self._collection.ensure_index(index_spec,
|
||||||
background=background, **index_opts)
|
background=background, **index_opts)
|
||||||
|
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _build_index_spec(cls, doc_cls, spec):
|
||||||
|
"""Build a PyMongo index spec from a MongoEngine index spec.
|
||||||
|
"""
|
||||||
|
if isinstance(spec, basestring):
|
||||||
|
spec = {'fields': [spec]}
|
||||||
|
if isinstance(spec, (list, tuple)):
|
||||||
|
spec = {'fields': spec}
|
||||||
|
|
||||||
|
index_list = []
|
||||||
|
use_types = doc_cls._meta.get('allow_inheritance', True)
|
||||||
|
for key in spec['fields']:
|
||||||
|
# Get ASCENDING direction from +, DESCENDING from -, and GEO2D from *
|
||||||
|
direction = pymongo.ASCENDING
|
||||||
|
if key.startswith("-"):
|
||||||
|
direction = pymongo.DESCENDING
|
||||||
|
elif key.startswith("*"):
|
||||||
|
direction = pymongo.GEO2D
|
||||||
|
if key.startswith(("+", "-", "*")):
|
||||||
|
key = key[1:]
|
||||||
|
|
||||||
|
# Use real field name, do it manually because we need field
|
||||||
|
# objects for the next part (list field checking)
|
||||||
|
parts = key.split('.')
|
||||||
|
fields = QuerySet._lookup_field(doc_cls, parts)
|
||||||
|
parts = [field if field == '_id' else field.db_field for field in fields]
|
||||||
|
key = '.'.join(parts)
|
||||||
|
index_list.append((key, direction))
|
||||||
|
|
||||||
|
# Check if a list field is being used, don't use _types if it is
|
||||||
|
if use_types and not all(f._index_with_types for f in fields):
|
||||||
|
use_types = False
|
||||||
|
|
||||||
|
# If _types is being used, prepend it to every specified index
|
||||||
|
index_types = doc_cls._meta.get('index_types', True)
|
||||||
|
allow_inheritance = doc_cls._meta.get('allow_inheritance')
|
||||||
|
if spec.get('types', index_types) and allow_inheritance and use_types and direction is not pymongo.GEO2D:
|
||||||
|
index_list.insert(0, ('_types', 1))
|
||||||
|
|
||||||
|
spec['fields'] = index_list
|
||||||
|
if spec.get('sparse', False) and len(spec['fields']) > 1:
|
||||||
|
raise ValueError(
|
||||||
|
'Sparse indexes can only have one field in them. '
|
||||||
|
'See https://jira.mongodb.org/browse/SERVER-2193')
|
||||||
|
|
||||||
|
return spec
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _reset_already_indexed(cls, document=None):
|
||||||
|
"""Helper to reset already indexed, can be useful for testing purposes"""
|
||||||
|
if document:
|
||||||
|
cls.__already_indexed.discard(document)
|
||||||
|
cls.__already_indexed.clear()
|
||||||
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def _collection(self):
|
def _collection(self):
|
||||||
"""Property that returns the collection object. This allows us to
|
"""Property that returns the collection object. This allows us to
|
||||||
@ -613,10 +614,11 @@ class QuerySet(object):
|
|||||||
continue
|
continue
|
||||||
if field is None:
|
if field is None:
|
||||||
# Look up first field from the document
|
# Look up first field from the document
|
||||||
if field_name == 'pk':
|
if field_name in ('pk', 'id', '_id'):
|
||||||
# Deal with "primary key" alias
|
# Deal with "primary key" alias
|
||||||
field_name = document._meta['id_field']
|
field_name = document._meta['id_field'] or '_id'
|
||||||
if field_name in document._fields:
|
field = "_id"
|
||||||
|
elif field_name in document._fields:
|
||||||
field = document._fields[field_name]
|
field = document._fields[field_name]
|
||||||
elif document._dynamic:
|
elif document._dynamic:
|
||||||
from base import BaseDynamicField
|
from base import BaseDynamicField
|
||||||
|
2
setup.py
2
setup.py
@ -48,6 +48,6 @@ setup(name='mongoengine',
|
|||||||
platforms=['any'],
|
platforms=['any'],
|
||||||
classifiers=CLASSIFIERS,
|
classifiers=CLASSIFIERS,
|
||||||
install_requires=['pymongo'],
|
install_requires=['pymongo'],
|
||||||
test_suite='tests',
|
test_suite='tests.bugfix',
|
||||||
tests_require=['blinker', 'django>=1.3', 'PIL']
|
tests_require=['blinker', 'django>=1.3', 'PIL']
|
||||||
)
|
)
|
||||||
|
@ -864,6 +864,26 @@ class DocumentTest(unittest.TestCase):
|
|||||||
query_plan = Test.objects(a=1).only('a').exclude('id').explain()
|
query_plan = Test.objects(a=1).only('a').exclude('id').explain()
|
||||||
self.assertTrue(query_plan['indexOnly'])
|
self.assertTrue(query_plan['indexOnly'])
|
||||||
|
|
||||||
|
def test_index_on_id(self):
|
||||||
|
|
||||||
|
class BlogPost(Document):
|
||||||
|
meta = {
|
||||||
|
'indexes': [
|
||||||
|
['categories', 'id']
|
||||||
|
],
|
||||||
|
'allow_inheritance': False
|
||||||
|
}
|
||||||
|
|
||||||
|
title = StringField(required=True)
|
||||||
|
description = StringField(required=True)
|
||||||
|
categories = ListField()
|
||||||
|
|
||||||
|
BlogPost.drop_collection()
|
||||||
|
|
||||||
|
indexes = BlogPost.objects._collection.index_information()
|
||||||
|
self.assertEquals(indexes['categories_1__id_1']['key'],
|
||||||
|
[('categories', 1), ('_id', 1)])
|
||||||
|
|
||||||
def test_hint(self):
|
def test_hint(self):
|
||||||
|
|
||||||
class BlogPost(Document):
|
class BlogPost(Document):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user