PYTHON-314, PYTHON-744 - Hint by index name, count with hint.
This change introduces two closely related features. Cursor.hint now accepts the name of an index as an alternative to passing the index spec. Cursor.count will now pass the hint, if one was specified, to the count command. Count with hint is only supported by MongoDB 2.6 and newer.
This commit is contained in:
parent
91622e62d5
commit
1ac607c447
@ -700,6 +700,12 @@ class Cursor(object):
|
||||
`with_limit_and_skip` to ``True`` if that is the desired behavior.
|
||||
Raises :class:`~pymongo.errors.OperationFailure` on a database error.
|
||||
|
||||
When used with MongoDB >= 2.6, :meth:`~count` uses any :meth:`~hint`
|
||||
applied to the query. In the following example the hint is passed to
|
||||
the count command:
|
||||
|
||||
collection.find({'field': 'value'}).hint('field_1').count()
|
||||
|
||||
With :class:`~pymongo.mongo_replica_set_client.MongoReplicaSetClient`
|
||||
or :class:`~pymongo.master_slave_connection.MasterSlaveConnection`,
|
||||
if `read_preference` is not
|
||||
@ -721,6 +727,9 @@ class Cursor(object):
|
||||
|
||||
collection.find({}, network_timeout=1).count()
|
||||
|
||||
.. versionchanged:: 2.8
|
||||
The :meth:`~count` method now supports :meth:`~hint`.
|
||||
|
||||
.. versionadded:: 1.1.1
|
||||
The `with_limit_and_skip` parameter.
|
||||
:meth:`~pymongo.cursor.Cursor.__len__` was deprecated in favor of
|
||||
@ -742,6 +751,9 @@ class Cursor(object):
|
||||
if self.__comment:
|
||||
command['$comment'] = self.__comment
|
||||
|
||||
if self.__hint is not None:
|
||||
command['hint'] = self.__hint
|
||||
|
||||
if with_limit_and_skip:
|
||||
if self.__limit:
|
||||
command["limit"] = self.__limit
|
||||
@ -834,20 +846,26 @@ class Cursor(object):
|
||||
|
||||
`index` should be an index as passed to
|
||||
:meth:`~pymongo.collection.Collection.create_index`
|
||||
(e.g. ``[('field', ASCENDING)]``). If `index`
|
||||
is ``None`` any existing hints for this query are cleared. The
|
||||
last hint applied to this cursor takes precedence over all
|
||||
others.
|
||||
(e.g. ``[('field', ASCENDING)]``) or the name of the index.
|
||||
If `index` is ``None`` any existing hint for this query is
|
||||
cleared. The last hint applied to this cursor takes precedence
|
||||
over all others.
|
||||
|
||||
:Parameters:
|
||||
- `index`: index to hint on (as an index specifier)
|
||||
|
||||
.. versionchanged:: 2.8
|
||||
The :meth:`~hint` method accepts the name of the index.
|
||||
"""
|
||||
self.__check_okay_to_chain()
|
||||
if index is None:
|
||||
self.__hint = None
|
||||
return self
|
||||
|
||||
self.__hint = helpers._index_document(index)
|
||||
if isinstance(index, basestring):
|
||||
self.__hint = index
|
||||
else:
|
||||
self.__hint = helpers._index_document(index)
|
||||
return self
|
||||
|
||||
def comment(self, comment):
|
||||
|
||||
@ -173,7 +173,18 @@ class TestCursor(unittest.TestCase):
|
||||
break
|
||||
self.assertRaises(InvalidOperation, a.hint, spec)
|
||||
|
||||
self.assertRaises(TypeError, db.test.find().hint, index)
|
||||
def test_hint_by_name(self):
|
||||
db = self.db
|
||||
db.test.drop()
|
||||
|
||||
for i in range(100):
|
||||
db.test.insert({'i': i})
|
||||
|
||||
db.test.create_index([('i', DESCENDING)], name='fooindex')
|
||||
first = db.test.find().next()
|
||||
self.assertEqual(0, first.get('i'))
|
||||
first = db.test.find().hint('fooindex').next()
|
||||
self.assertEqual(99, first.get('i'))
|
||||
|
||||
def test_limit(self):
|
||||
db = self.db
|
||||
@ -495,6 +506,40 @@ class TestCursor(unittest.TestCase):
|
||||
|
||||
self.assertEqual(0, db.test.acollectionthatdoesntexist.find().count())
|
||||
|
||||
def test_count_with_hint(self):
|
||||
collection = self.db.test
|
||||
collection.drop()
|
||||
|
||||
collection.save({'i': 1})
|
||||
collection.save({'i': 2})
|
||||
self.assertEqual(2, collection.find().count())
|
||||
|
||||
collection.create_index([('i', 1)])
|
||||
|
||||
self.assertEqual(1, collection.find({'i': 1}).hint("_id_").count())
|
||||
self.assertEqual(2, collection.find().hint("_id_").count())
|
||||
|
||||
if version.at_least(self.client, (2, 6, 0)):
|
||||
# Count supports hint
|
||||
self.assertRaises(OperationFailure,
|
||||
collection.find({'i': 1}).hint("BAD HINT").count)
|
||||
else:
|
||||
# Hint is ignored
|
||||
self.assertEqual(
|
||||
1, collection.find({'i': 1}).hint("BAD HINT").count())
|
||||
|
||||
# Create a sparse index which should have no entries.
|
||||
collection.create_index([('x', 1)], sparse=True)
|
||||
|
||||
if version.at_least(self.client, (2, 6, 0)):
|
||||
# Count supports hint
|
||||
self.assertEqual(0, collection.find({'i': 1}).hint("x_1").count())
|
||||
else:
|
||||
# Hint is ignored
|
||||
self.assertEqual(1, collection.find({'i': 1}).hint("x_1").count())
|
||||
|
||||
self.assertEqual(2, collection.find().hint("x_1").count())
|
||||
|
||||
def test_where(self):
|
||||
db = self.db
|
||||
db.test.drop()
|
||||
|
||||
Loading…
Reference in New Issue
Block a user