PYTHON-2036 Expand CRUD API support for index hinting (also PYTHON-2015, PYTHON-2104, PYTHON-2134)
This commit is contained in:
parent
a460725f6b
commit
1323ef15cb
@ -156,6 +156,7 @@ class _Bulk(object):
|
||||
self.bypass_doc_val = bypass_document_validation
|
||||
self.uses_collation = False
|
||||
self.uses_array_filters = False
|
||||
self.uses_hint = False
|
||||
self.is_retryable = True
|
||||
self.retrying = False
|
||||
self.started_retryable_write = False
|
||||
@ -180,7 +181,7 @@ class _Bulk(object):
|
||||
self.ops.append((_INSERT, document))
|
||||
|
||||
def add_update(self, selector, update, multi=False, upsert=False,
|
||||
collation=None, array_filters=None):
|
||||
collation=None, array_filters=None, hint=None):
|
||||
"""Create an update document and add it to the list of ops.
|
||||
"""
|
||||
validate_ok_for_update(update)
|
||||
@ -193,13 +194,16 @@ class _Bulk(object):
|
||||
if array_filters is not None:
|
||||
self.uses_array_filters = True
|
||||
cmd['arrayFilters'] = array_filters
|
||||
if hint is not None:
|
||||
self.uses_hint = True
|
||||
cmd['hint'] = hint
|
||||
if multi:
|
||||
# A bulk_write containing an update_many is not retryable.
|
||||
self.is_retryable = False
|
||||
self.ops.append((_UPDATE, cmd))
|
||||
|
||||
def add_replace(self, selector, replacement, upsert=False,
|
||||
collation=None):
|
||||
collation=None, hint=None):
|
||||
"""Create a replace document and add it to the list of ops.
|
||||
"""
|
||||
validate_ok_for_replace(replacement)
|
||||
@ -209,6 +213,9 @@ class _Bulk(object):
|
||||
if collation is not None:
|
||||
self.uses_collation = True
|
||||
cmd['collation'] = collation
|
||||
if hint is not None:
|
||||
self.uses_hint = True
|
||||
cmd['hint'] = hint
|
||||
self.ops.append((_UPDATE, cmd))
|
||||
|
||||
def add_delete(self, selector, limit, collation=None):
|
||||
@ -252,9 +259,13 @@ class _Bulk(object):
|
||||
|
||||
def _execute_command(self, generator, write_concern, session,
|
||||
sock_info, op_id, retryable, full_result):
|
||||
if sock_info.max_wire_version < 5 and self.uses_collation:
|
||||
raise ConfigurationError(
|
||||
'Must be connected to MongoDB 3.4+ to use a collation.')
|
||||
if sock_info.max_wire_version < 5:
|
||||
if self.uses_collation:
|
||||
raise ConfigurationError(
|
||||
'Must be connected to MongoDB 3.4+ to use a collation.')
|
||||
if self.uses_hint:
|
||||
raise ConfigurationError(
|
||||
'Must be connected to MongoDB 3.4+ to use hint.')
|
||||
if sock_info.max_wire_version < 6 and self.uses_array_filters:
|
||||
raise ConfigurationError(
|
||||
'Must be connected to MongoDB 3.6+ to use arrayFilters.')
|
||||
@ -428,6 +439,9 @@ class _Bulk(object):
|
||||
if self.uses_array_filters:
|
||||
raise ConfigurationError(
|
||||
'arrayFilters is unsupported for unacknowledged writes.')
|
||||
if self.uses_hint:
|
||||
raise ConfigurationError(
|
||||
'hint is unsupported for unacknowledged writes.')
|
||||
# Cannot have both unacknowledged writes and bypass document validation.
|
||||
if self.bypass_doc_val and sock_info.max_wire_version >= 4:
|
||||
raise OperationFailure("Cannot set bypass_document_validation with"
|
||||
|
||||
@ -761,7 +761,7 @@ class Collection(common.BaseObject):
|
||||
check_keys=True, multi=False, manipulate=False,
|
||||
write_concern=None, op_id=None, ordered=True,
|
||||
bypass_doc_val=False, collation=None, array_filters=None,
|
||||
session=None, retryable_write=False):
|
||||
hint=None, session=None, retryable_write=False):
|
||||
"""Internal update / replace helper."""
|
||||
common.validate_boolean("upsert", upsert)
|
||||
if manipulate:
|
||||
@ -791,6 +791,17 @@ class Collection(common.BaseObject):
|
||||
'arrayFilters is unsupported for unacknowledged writes.')
|
||||
else:
|
||||
update_doc['arrayFilters'] = array_filters
|
||||
if hint is not None:
|
||||
if sock_info.max_wire_version < 5:
|
||||
raise ConfigurationError(
|
||||
'Must be connected to MongoDB 3.4+ to use hint.')
|
||||
elif not acknowledged:
|
||||
raise ConfigurationError(
|
||||
'hint is unsupported for unacknowledged writes.')
|
||||
if not isinstance(hint, string_type):
|
||||
hint = helpers._index_document(hint)
|
||||
update_doc['hint'] = hint
|
||||
|
||||
command = SON([('update', self.name),
|
||||
('ordered', ordered),
|
||||
('updates', [update_doc])])
|
||||
@ -839,7 +850,7 @@ class Collection(common.BaseObject):
|
||||
check_keys=True, multi=False, manipulate=False,
|
||||
write_concern=None, op_id=None, ordered=True,
|
||||
bypass_doc_val=False, collation=None, array_filters=None,
|
||||
session=None):
|
||||
hint=None, session=None):
|
||||
"""Internal update / replace helper."""
|
||||
def _update(session, sock_info, retryable_write):
|
||||
return self._update(
|
||||
@ -847,7 +858,7 @@ class Collection(common.BaseObject):
|
||||
check_keys=check_keys, multi=multi, manipulate=manipulate,
|
||||
write_concern=write_concern, op_id=op_id, ordered=ordered,
|
||||
bypass_doc_val=bypass_doc_val, collation=collation,
|
||||
array_filters=array_filters, session=session,
|
||||
array_filters=array_filters, hint=hint, session=session,
|
||||
retryable_write=retryable_write)
|
||||
|
||||
return self.__database.client._retryable_write(
|
||||
@ -856,7 +867,7 @@ class Collection(common.BaseObject):
|
||||
|
||||
def replace_one(self, filter, replacement, upsert=False,
|
||||
bypass_document_validation=False, collation=None,
|
||||
session=None):
|
||||
hint=None, session=None):
|
||||
"""Replace a single document matching the filter.
|
||||
|
||||
>>> for doc in db.test.find({}):
|
||||
@ -893,27 +904,30 @@ class Collection(common.BaseObject):
|
||||
match the filter.
|
||||
- `bypass_document_validation`: (optional) If ``True``, allows the
|
||||
write to opt-out of document level validation. Default is
|
||||
``False``.
|
||||
``False``. This option is only supported on MongoDB 3.2 and above.
|
||||
- `collation` (optional): An instance of
|
||||
:class:`~pymongo.collation.Collation`. This option is only supported
|
||||
on MongoDB 3.4 and above.
|
||||
- `hint` (optional): An index to use to support the query
|
||||
predicate specified either by its string name, or in the same
|
||||
format as passed to
|
||||
:meth:`~pymongo.collection.Collection.create_index` (e.g.
|
||||
``[('field', ASCENDING)]``). This option is only supported on
|
||||
MongoDB 4.2 and above.
|
||||
- `session` (optional): a
|
||||
:class:`~pymongo.client_session.ClientSession`.
|
||||
|
||||
:Returns:
|
||||
- An instance of :class:`~pymongo.results.UpdateResult`.
|
||||
|
||||
.. note:: `bypass_document_validation` requires server version
|
||||
**>= 3.2**
|
||||
|
||||
.. versionchanged:: 3.11
|
||||
Added ``hint`` parameter.
|
||||
.. versionchanged:: 3.6
|
||||
Added ``session`` parameter.
|
||||
|
||||
.. versionchanged:: 3.4
|
||||
Added the `collation` option.
|
||||
|
||||
.. versionchanged:: 3.2
|
||||
Added bypass_document_validation support
|
||||
Added bypass_document_validation support.
|
||||
|
||||
.. versionadded:: 3.0
|
||||
"""
|
||||
@ -926,12 +940,13 @@ class Collection(common.BaseObject):
|
||||
filter, replacement, upsert,
|
||||
write_concern=write_concern,
|
||||
bypass_doc_val=bypass_document_validation,
|
||||
collation=collation, session=session),
|
||||
collation=collation, hint=hint, session=session),
|
||||
write_concern.acknowledged)
|
||||
|
||||
def update_one(self, filter, update, upsert=False,
|
||||
bypass_document_validation=False,
|
||||
collation=None, array_filters=None, session=None):
|
||||
collation=None, array_filters=None, hint=None,
|
||||
session=None):
|
||||
"""Update a single document matching the filter.
|
||||
|
||||
>>> for doc in db.test.find():
|
||||
@ -959,32 +974,35 @@ class Collection(common.BaseObject):
|
||||
match the filter.
|
||||
- `bypass_document_validation`: (optional) If ``True``, allows the
|
||||
write to opt-out of document level validation. Default is
|
||||
``False``.
|
||||
``False``. This option is only supported on MongoDB 3.2 and above.
|
||||
- `collation` (optional): An instance of
|
||||
:class:`~pymongo.collation.Collation`. This option is only supported
|
||||
on MongoDB 3.4 and above.
|
||||
- `array_filters` (optional): A list of filters specifying which
|
||||
array elements an update should apply. Requires MongoDB 3.6+.
|
||||
array elements an update should apply. This option is only
|
||||
supported on MongoDB 3.6 and above.
|
||||
- `hint` (optional): An index to use to support the query
|
||||
predicate specified either by its string name, or in the same
|
||||
format as passed to
|
||||
:meth:`~pymongo.collection.Collection.create_index` (e.g.
|
||||
``[('field', ASCENDING)]``). This option is only supported on
|
||||
MongoDB 4.2 and above.
|
||||
- `session` (optional): a
|
||||
:class:`~pymongo.client_session.ClientSession`.
|
||||
|
||||
:Returns:
|
||||
- An instance of :class:`~pymongo.results.UpdateResult`.
|
||||
|
||||
.. note:: `bypass_document_validation` requires server version
|
||||
**>= 3.2**
|
||||
|
||||
.. versionchanged:: 3.11
|
||||
Added ``hint`` parameter.
|
||||
.. versionchanged:: 3.9
|
||||
Added the ability to accept a pipeline as the `update`.
|
||||
|
||||
Added the ability to accept a pipeline as the ``update``.
|
||||
.. versionchanged:: 3.6
|
||||
Added the `array_filters` and ``session`` parameters.
|
||||
|
||||
Added the ``array_filters`` and ``session`` parameters.
|
||||
.. versionchanged:: 3.4
|
||||
Added the `collation` option.
|
||||
|
||||
Added the ``collation`` option.
|
||||
.. versionchanged:: 3.2
|
||||
Added bypass_document_validation support
|
||||
Added ``bypass_document_validation`` support.
|
||||
|
||||
.. versionadded:: 3.0
|
||||
"""
|
||||
@ -999,12 +1017,12 @@ class Collection(common.BaseObject):
|
||||
write_concern=write_concern,
|
||||
bypass_doc_val=bypass_document_validation,
|
||||
collation=collation, array_filters=array_filters,
|
||||
session=session),
|
||||
hint=hint, session=session),
|
||||
write_concern.acknowledged)
|
||||
|
||||
def update_many(self, filter, update, upsert=False, array_filters=None,
|
||||
bypass_document_validation=False, collation=None,
|
||||
session=None):
|
||||
hint=None, session=None):
|
||||
"""Update one or more documents that match the filter.
|
||||
|
||||
>>> for doc in db.test.find():
|
||||
@ -1032,32 +1050,35 @@ class Collection(common.BaseObject):
|
||||
match the filter.
|
||||
- `bypass_document_validation` (optional): If ``True``, allows the
|
||||
write to opt-out of document level validation. Default is
|
||||
``False``.
|
||||
``False``. This option is only supported on MongoDB 3.2 and above.
|
||||
- `collation` (optional): An instance of
|
||||
:class:`~pymongo.collation.Collation`. This option is only supported
|
||||
on MongoDB 3.4 and above.
|
||||
- `array_filters` (optional): A list of filters specifying which
|
||||
array elements an update should apply. Requires MongoDB 3.6+.
|
||||
array elements an update should apply. This option is only
|
||||
supported on MongoDB 3.6 and above.
|
||||
- `hint` (optional): An index to use to support the query
|
||||
predicate specified either by its string name, or in the same
|
||||
format as passed to
|
||||
:meth:`~pymongo.collection.Collection.create_index` (e.g.
|
||||
``[('field', ASCENDING)]``). This option is only supported on
|
||||
MongoDB 4.2 and above.
|
||||
- `session` (optional): a
|
||||
:class:`~pymongo.client_session.ClientSession`.
|
||||
|
||||
:Returns:
|
||||
- An instance of :class:`~pymongo.results.UpdateResult`.
|
||||
|
||||
.. note:: `bypass_document_validation` requires server version
|
||||
**>= 3.2**
|
||||
|
||||
.. versionchanged:: 3.11
|
||||
Added ``hint`` parameter.
|
||||
.. versionchanged:: 3.9
|
||||
Added the ability to accept a pipeline as the `update`.
|
||||
|
||||
.. versionchanged:: 3.6
|
||||
Added ``array_filters`` and ``session`` parameters.
|
||||
|
||||
.. versionchanged:: 3.4
|
||||
Added the `collation` option.
|
||||
|
||||
.. versionchanged:: 3.2
|
||||
Added bypass_document_validation support
|
||||
Added bypass_document_validation support.
|
||||
|
||||
.. versionadded:: 3.0
|
||||
"""
|
||||
@ -1072,7 +1093,7 @@ class Collection(common.BaseObject):
|
||||
write_concern=write_concern,
|
||||
bypass_doc_val=bypass_document_validation,
|
||||
collation=collation, array_filters=array_filters,
|
||||
session=session),
|
||||
hint=hint, session=session),
|
||||
write_concern.acknowledged)
|
||||
|
||||
def drop(self, session=None):
|
||||
@ -2834,7 +2855,8 @@ class Collection(common.BaseObject):
|
||||
|
||||
def __find_and_modify(self, filter, projection, sort, upsert=None,
|
||||
return_document=ReturnDocument.BEFORE,
|
||||
array_filters=None, session=None, **kwargs):
|
||||
array_filters=None, hint=None, session=None,
|
||||
**kwargs):
|
||||
"""Internal findAndModify helper."""
|
||||
|
||||
common.validate_is_mapping("filter", filter)
|
||||
@ -2854,6 +2876,9 @@ class Collection(common.BaseObject):
|
||||
if upsert is not None:
|
||||
common.validate_boolean("upsert", upsert)
|
||||
cmd["upsert"] = upsert
|
||||
if hint is not None:
|
||||
if not isinstance(hint, string_type):
|
||||
hint = helpers._index_document(hint)
|
||||
|
||||
write_concern = self._write_concern_for_cmd(cmd, session)
|
||||
|
||||
@ -2868,6 +2893,11 @@ class Collection(common.BaseObject):
|
||||
'arrayFilters is unsupported for unacknowledged '
|
||||
'writes.')
|
||||
cmd["arrayFilters"] = array_filters
|
||||
if hint is not None:
|
||||
if sock_info.max_wire_version < 8:
|
||||
raise ConfigurationError(
|
||||
'Must be connected to MongoDB 4.2+ to use hint.')
|
||||
cmd['hint'] = hint
|
||||
if (sock_info.max_wire_version >= 4 and
|
||||
not write_concern.is_server_default):
|
||||
cmd['writeConcern'] = write_concern.document
|
||||
@ -2952,7 +2982,7 @@ class Collection(common.BaseObject):
|
||||
def find_one_and_replace(self, filter, replacement,
|
||||
projection=None, sort=None, upsert=False,
|
||||
return_document=ReturnDocument.BEFORE,
|
||||
session=None, **kwargs):
|
||||
hint=None, session=None, **kwargs):
|
||||
"""Finds a single document and replaces it, returning either the
|
||||
original or the replaced document.
|
||||
|
||||
@ -2994,16 +3024,24 @@ class Collection(common.BaseObject):
|
||||
if no document matches. If
|
||||
:attr:`ReturnDocument.AFTER`, returns the replaced
|
||||
or inserted document.
|
||||
- `hint` (optional): An index to use to support the query
|
||||
predicate specified either by its string name, or in the same
|
||||
format as passed to
|
||||
:meth:`~pymongo.collection.Collection.create_index` (e.g.
|
||||
``[('field', ASCENDING)]``). This option is only supported on
|
||||
MongoDB 4.4 and above.
|
||||
- `session` (optional): a
|
||||
:class:`~pymongo.client_session.ClientSession`.
|
||||
- `**kwargs` (optional): additional command arguments can be passed
|
||||
as keyword arguments (for example maxTimeMS can be used with
|
||||
recent server versions).
|
||||
|
||||
.. versionchanged:: 3.11
|
||||
Added the ``hint`` option.
|
||||
.. versionchanged:: 3.6
|
||||
Added ``session`` parameter.
|
||||
.. versionchanged:: 3.4
|
||||
Added the `collation` option.
|
||||
Added the ``collation`` option.
|
||||
.. versionchanged:: 3.2
|
||||
Respects write concern.
|
||||
|
||||
@ -3019,12 +3057,13 @@ class Collection(common.BaseObject):
|
||||
kwargs['update'] = replacement
|
||||
return self.__find_and_modify(filter, projection,
|
||||
sort, upsert, return_document,
|
||||
session=session, **kwargs)
|
||||
hint=hint, session=session, **kwargs)
|
||||
|
||||
def find_one_and_update(self, filter, update,
|
||||
projection=None, sort=None, upsert=False,
|
||||
return_document=ReturnDocument.BEFORE,
|
||||
array_filters=None, session=None, **kwargs):
|
||||
array_filters=None, hint=None, session=None,
|
||||
**kwargs):
|
||||
"""Finds a single document and updates it, returning either the
|
||||
original or the updated document.
|
||||
|
||||
@ -3104,19 +3143,28 @@ class Collection(common.BaseObject):
|
||||
:attr:`ReturnDocument.AFTER`, returns the updated
|
||||
or inserted document.
|
||||
- `array_filters` (optional): A list of filters specifying which
|
||||
array elements an update should apply. Requires MongoDB 3.6+.
|
||||
array elements an update should apply. This option is only
|
||||
supported on MongoDB 3.6 and above.
|
||||
- `hint` (optional): An index to use to support the query
|
||||
predicate specified either by its string name, or in the same
|
||||
format as passed to
|
||||
:meth:`~pymongo.collection.Collection.create_index` (e.g.
|
||||
``[('field', ASCENDING)]``). This option is only supported on
|
||||
MongoDB 4.4 and above.
|
||||
- `session` (optional): a
|
||||
:class:`~pymongo.client_session.ClientSession`.
|
||||
- `**kwargs` (optional): additional command arguments can be passed
|
||||
as keyword arguments (for example maxTimeMS can be used with
|
||||
recent server versions).
|
||||
|
||||
.. versionchanged:: 3.11
|
||||
Added the ``hint`` option.
|
||||
.. versionchanged:: 3.9
|
||||
Added the ability to accept a pipeline as the `update`.
|
||||
Added the ability to accept a pipeline as the ``update``.
|
||||
.. versionchanged:: 3.6
|
||||
Added the `array_filters` and `session` options.
|
||||
Added the ``array_filters`` and ``session`` options.
|
||||
.. versionchanged:: 3.4
|
||||
Added the `collation` option.
|
||||
Added the ``collation`` option.
|
||||
.. versionchanged:: 3.2
|
||||
Respects write concern.
|
||||
|
||||
@ -3133,7 +3181,8 @@ class Collection(common.BaseObject):
|
||||
kwargs['update'] = update
|
||||
return self.__find_and_modify(filter, projection,
|
||||
sort, upsert, return_document,
|
||||
array_filters, session=session, **kwargs)
|
||||
array_filters, hint=hint,
|
||||
session=session, **kwargs)
|
||||
|
||||
def save(self, to_save, manipulate=True, check_keys=True, **kwargs):
|
||||
"""Save a document in this collection.
|
||||
|
||||
@ -14,6 +14,9 @@
|
||||
|
||||
"""Operation class definitions."""
|
||||
|
||||
from bson.py3compat import string_type
|
||||
|
||||
from pymongo import helpers
|
||||
from pymongo.common import validate_boolean, validate_is_mapping, validate_list
|
||||
from pymongo.collation import validate_collation_or_none
|
||||
from pymongo.helpers import _gen_index_name, _index_document, _index_list
|
||||
@ -136,9 +139,10 @@ class DeleteMany(object):
|
||||
class ReplaceOne(object):
|
||||
"""Represents a replace_one operation."""
|
||||
|
||||
__slots__ = ("_filter", "_doc", "_upsert", "_collation")
|
||||
__slots__ = ("_filter", "_doc", "_upsert", "_collation", "_hint")
|
||||
|
||||
def __init__(self, filter, replacement, upsert=False, collation=None):
|
||||
def __init__(self, filter, replacement, upsert=False, collation=None,
|
||||
hint=None):
|
||||
"""Create a ReplaceOne instance.
|
||||
|
||||
For use with :meth:`~pymongo.collection.Collection.bulk_write`.
|
||||
@ -151,65 +155,43 @@ class ReplaceOne(object):
|
||||
- `collation` (optional): An instance of
|
||||
:class:`~pymongo.collation.Collation`. This option is only
|
||||
supported on MongoDB 3.4 and above.
|
||||
- `hint` (optional): An index to use to support the query
|
||||
predicate specified either by its string name, or in the same
|
||||
format as passed to
|
||||
:meth:`~pymongo.collection.Collection.create_index` (e.g.
|
||||
``[('field', ASCENDING)]``). This option is only supported on
|
||||
MongoDB 4.2 and above.
|
||||
|
||||
.. versionchanged:: 3.11
|
||||
Added the ``hint`` option.
|
||||
.. versionchanged:: 3.5
|
||||
Added the `collation` option.
|
||||
Added the ``collation`` option.
|
||||
"""
|
||||
if filter is not None:
|
||||
validate_is_mapping("filter", filter)
|
||||
if upsert is not None:
|
||||
validate_boolean("upsert", upsert)
|
||||
if hint is not None:
|
||||
if not isinstance(hint, string_type):
|
||||
hint = helpers._index_document(hint)
|
||||
|
||||
self._filter = filter
|
||||
self._doc = replacement
|
||||
self._upsert = upsert
|
||||
self._collation = collation
|
||||
self._hint = hint
|
||||
|
||||
def _add_to_bulk(self, bulkobj):
|
||||
"""Add this operation to the _Bulk instance `bulkobj`."""
|
||||
bulkobj.add_replace(self._filter, self._doc, self._upsert,
|
||||
collation=self._collation)
|
||||
|
||||
def __eq__(self, other):
|
||||
if type(other) == type(self):
|
||||
return (
|
||||
(other._filter, other._doc, other._upsert, other._collation) ==
|
||||
(self._filter, self._doc, self._upsert, self._collation))
|
||||
return NotImplemented
|
||||
|
||||
def __ne__(self, other):
|
||||
return not self == other
|
||||
|
||||
def __repr__(self):
|
||||
return "%s(%r, %r, %r, %r)" % (
|
||||
self.__class__.__name__, self._filter, self._doc, self._upsert,
|
||||
self._collation)
|
||||
|
||||
|
||||
class _UpdateOp(object):
|
||||
"""Private base class for update operations."""
|
||||
|
||||
__slots__ = ("_filter", "_doc", "_upsert", "_collation", "_array_filters")
|
||||
|
||||
def __init__(self, filter, doc, upsert, collation, array_filters):
|
||||
if filter is not None:
|
||||
validate_is_mapping("filter", filter)
|
||||
if upsert is not None:
|
||||
validate_boolean("upsert", upsert)
|
||||
if array_filters is not None:
|
||||
validate_list("array_filters", array_filters)
|
||||
self._filter = filter
|
||||
self._doc = doc
|
||||
self._upsert = upsert
|
||||
self._collation = collation
|
||||
self._array_filters = array_filters
|
||||
collation=self._collation, hint=self._hint)
|
||||
|
||||
def __eq__(self, other):
|
||||
if type(other) == type(self):
|
||||
return (
|
||||
(other._filter, other._doc, other._upsert, other._collation,
|
||||
other._array_filters) ==
|
||||
(self._filter, self._doc, self._upsert, self._collation,
|
||||
self._array_filters))
|
||||
other._hint) == (self._filter, self._doc, self._upsert,
|
||||
self._collation, other._hint))
|
||||
return NotImplemented
|
||||
|
||||
def __ne__(self, other):
|
||||
@ -218,7 +200,50 @@ class _UpdateOp(object):
|
||||
def __repr__(self):
|
||||
return "%s(%r, %r, %r, %r, %r)" % (
|
||||
self.__class__.__name__, self._filter, self._doc, self._upsert,
|
||||
self._collation, self._array_filters)
|
||||
self._collation, self._hint)
|
||||
|
||||
|
||||
class _UpdateOp(object):
|
||||
"""Private base class for update operations."""
|
||||
|
||||
__slots__ = ("_filter", "_doc", "_upsert", "_collation", "_array_filters",
|
||||
"_hint")
|
||||
|
||||
def __init__(self, filter, doc, upsert, collation, array_filters, hint):
|
||||
if filter is not None:
|
||||
validate_is_mapping("filter", filter)
|
||||
if upsert is not None:
|
||||
validate_boolean("upsert", upsert)
|
||||
if array_filters is not None:
|
||||
validate_list("array_filters", array_filters)
|
||||
if hint is not None:
|
||||
if not isinstance(hint, string_type):
|
||||
hint = helpers._index_document(hint)
|
||||
|
||||
|
||||
self._filter = filter
|
||||
self._doc = doc
|
||||
self._upsert = upsert
|
||||
self._collation = collation
|
||||
self._array_filters = array_filters
|
||||
self._hint = hint
|
||||
|
||||
def __eq__(self, other):
|
||||
if type(other) == type(self):
|
||||
return (
|
||||
(other._filter, other._doc, other._upsert, other._collation,
|
||||
other._array_filters, other._hint) ==
|
||||
(self._filter, self._doc, self._upsert, self._collation,
|
||||
self._array_filters, self._hint))
|
||||
return NotImplemented
|
||||
|
||||
def __ne__(self, other):
|
||||
return not self == other
|
||||
|
||||
def __repr__(self):
|
||||
return "%s(%r, %r, %r, %r, %r, %r)" % (
|
||||
self.__class__.__name__, self._filter, self._doc, self._upsert,
|
||||
self._collation, self._array_filters, self._hint)
|
||||
|
||||
|
||||
class UpdateOne(_UpdateOp):
|
||||
@ -227,7 +252,7 @@ class UpdateOne(_UpdateOp):
|
||||
__slots__ = ()
|
||||
|
||||
def __init__(self, filter, update, upsert=False, collation=None,
|
||||
array_filters=None):
|
||||
array_filters=None, hint=None):
|
||||
"""Represents an update_one operation.
|
||||
|
||||
For use with :meth:`~pymongo.collection.Collection.bulk_write`.
|
||||
@ -242,7 +267,15 @@ class UpdateOne(_UpdateOp):
|
||||
supported on MongoDB 3.4 and above.
|
||||
- `array_filters` (optional): A list of filters specifying which
|
||||
array elements an update should apply. Requires MongoDB 3.6+.
|
||||
- `hint` (optional): An index to use to support the query
|
||||
predicate specified either by its string name, or in the same
|
||||
format as passed to
|
||||
:meth:`~pymongo.collection.Collection.create_index` (e.g.
|
||||
``[('field', ASCENDING)]``). This option is only supported on
|
||||
MongoDB 4.2 and above.
|
||||
|
||||
.. versionchanged:: 3.11
|
||||
Added the `hint` option.
|
||||
.. versionchanged:: 3.9
|
||||
Added the ability to accept a pipeline as the `update`.
|
||||
.. versionchanged:: 3.6
|
||||
@ -251,13 +284,14 @@ class UpdateOne(_UpdateOp):
|
||||
Added the `collation` option.
|
||||
"""
|
||||
super(UpdateOne, self).__init__(filter, update, upsert, collation,
|
||||
array_filters)
|
||||
array_filters, hint)
|
||||
|
||||
def _add_to_bulk(self, bulkobj):
|
||||
"""Add this operation to the _Bulk instance `bulkobj`."""
|
||||
bulkobj.add_update(self._filter, self._doc, False, self._upsert,
|
||||
collation=self._collation,
|
||||
array_filters=self._array_filters)
|
||||
array_filters=self._array_filters,
|
||||
hint=self._hint)
|
||||
|
||||
|
||||
class UpdateMany(_UpdateOp):
|
||||
@ -266,7 +300,7 @@ class UpdateMany(_UpdateOp):
|
||||
__slots__ = ()
|
||||
|
||||
def __init__(self, filter, update, upsert=False, collation=None,
|
||||
array_filters=None):
|
||||
array_filters=None, hint=None):
|
||||
"""Create an UpdateMany instance.
|
||||
|
||||
For use with :meth:`~pymongo.collection.Collection.bulk_write`.
|
||||
@ -281,7 +315,15 @@ class UpdateMany(_UpdateOp):
|
||||
supported on MongoDB 3.4 and above.
|
||||
- `array_filters` (optional): A list of filters specifying which
|
||||
array elements an update should apply. Requires MongoDB 3.6+.
|
||||
- `hint` (optional): An index to use to support the query
|
||||
predicate specified either by its string name, or in the same
|
||||
format as passed to
|
||||
:meth:`~pymongo.collection.Collection.create_index` (e.g.
|
||||
``[('field', ASCENDING)]``). This option is only supported on
|
||||
MongoDB 4.2 and above.
|
||||
|
||||
.. versionchanged:: 3.11
|
||||
Added the `hint` option.
|
||||
.. versionchanged:: 3.9
|
||||
Added the ability to accept a pipeline as the `update`.
|
||||
.. versionchanged:: 3.6
|
||||
@ -290,13 +332,14 @@ class UpdateMany(_UpdateOp):
|
||||
Added the `collation` option.
|
||||
"""
|
||||
super(UpdateMany, self).__init__(filter, update, upsert, collation,
|
||||
array_filters)
|
||||
array_filters, hint)
|
||||
|
||||
def _add_to_bulk(self, bulkobj):
|
||||
"""Add this operation to the _Bulk instance `bulkobj`."""
|
||||
bulkobj.add_update(self._filter, self._doc, True, self._upsert,
|
||||
collation=self._collation,
|
||||
array_filters=self._array_filters)
|
||||
array_filters=self._array_filters,
|
||||
hint=self._hint)
|
||||
|
||||
|
||||
class IndexModel(object):
|
||||
|
||||
366
test/crud/v2/bulkWrite-update-hint.json
Normal file
366
test/crud/v2/bulkWrite-update-hint.json
Normal file
@ -0,0 +1,366 @@
|
||||
{
|
||||
"runOn": [
|
||||
{
|
||||
"minServerVersion": "4.2.0"
|
||||
}
|
||||
],
|
||||
"data": [
|
||||
{
|
||||
"_id": 1,
|
||||
"x": 11
|
||||
},
|
||||
{
|
||||
"_id": 2,
|
||||
"x": 22
|
||||
},
|
||||
{
|
||||
"_id": 3,
|
||||
"x": 33
|
||||
},
|
||||
{
|
||||
"_id": 4,
|
||||
"x": 44
|
||||
}
|
||||
],
|
||||
"collection_name": "test_bulkwrite_update_hint",
|
||||
"tests": [
|
||||
{
|
||||
"description": "BulkWrite updateOne with update hints",
|
||||
"operations": [
|
||||
{
|
||||
"name": "bulkWrite",
|
||||
"arguments": {
|
||||
"requests": [
|
||||
{
|
||||
"name": "updateOne",
|
||||
"arguments": {
|
||||
"filter": {
|
||||
"_id": 1
|
||||
},
|
||||
"update": {
|
||||
"$inc": {
|
||||
"x": 1
|
||||
}
|
||||
},
|
||||
"hint": "_id_"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "updateOne",
|
||||
"arguments": {
|
||||
"filter": {
|
||||
"_id": 1
|
||||
},
|
||||
"update": {
|
||||
"$inc": {
|
||||
"x": 1
|
||||
}
|
||||
},
|
||||
"hint": {
|
||||
"_id": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"options": {
|
||||
"ordered": true
|
||||
}
|
||||
},
|
||||
"result": {
|
||||
"deletedCount": 0,
|
||||
"insertedCount": 0,
|
||||
"insertedIds": {},
|
||||
"matchedCount": 2,
|
||||
"modifiedCount": 2,
|
||||
"upsertedCount": 0,
|
||||
"upsertedIds": {}
|
||||
}
|
||||
}
|
||||
],
|
||||
"expectations": [
|
||||
{
|
||||
"command_started_event": {
|
||||
"command": {
|
||||
"update": "test_bulkwrite_update_hint",
|
||||
"updates": [
|
||||
{
|
||||
"q": {
|
||||
"_id": 1
|
||||
},
|
||||
"u": {
|
||||
"$inc": {
|
||||
"x": 1
|
||||
}
|
||||
},
|
||||
"hint": "_id_"
|
||||
},
|
||||
{
|
||||
"q": {
|
||||
"_id": 1
|
||||
},
|
||||
"u": {
|
||||
"$inc": {
|
||||
"x": 1
|
||||
}
|
||||
},
|
||||
"hint": {
|
||||
"_id": 1
|
||||
}
|
||||
}
|
||||
],
|
||||
"ordered": true
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"outcome": {
|
||||
"collection": {
|
||||
"data": [
|
||||
{
|
||||
"_id": 1,
|
||||
"x": 13
|
||||
},
|
||||
{
|
||||
"_id": 2,
|
||||
"x": 22
|
||||
},
|
||||
{
|
||||
"_id": 3,
|
||||
"x": 33
|
||||
},
|
||||
{
|
||||
"_id": 4,
|
||||
"x": 44
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "BulkWrite updateMany with update hints",
|
||||
"operations": [
|
||||
{
|
||||
"name": "bulkWrite",
|
||||
"arguments": {
|
||||
"requests": [
|
||||
{
|
||||
"name": "updateMany",
|
||||
"arguments": {
|
||||
"filter": {
|
||||
"_id": {
|
||||
"$lt": 3
|
||||
}
|
||||
},
|
||||
"update": {
|
||||
"$inc": {
|
||||
"x": 1
|
||||
}
|
||||
},
|
||||
"hint": "_id_"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "updateMany",
|
||||
"arguments": {
|
||||
"filter": {
|
||||
"_id": {
|
||||
"$lt": 3
|
||||
}
|
||||
},
|
||||
"update": {
|
||||
"$inc": {
|
||||
"x": 1
|
||||
}
|
||||
},
|
||||
"hint": {
|
||||
"_id": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"options": {
|
||||
"ordered": true
|
||||
}
|
||||
},
|
||||
"result": {
|
||||
"deletedCount": 0,
|
||||
"insertedCount": 0,
|
||||
"insertedIds": {},
|
||||
"matchedCount": 4,
|
||||
"modifiedCount": 4,
|
||||
"upsertedCount": 0,
|
||||
"upsertedIds": {}
|
||||
}
|
||||
}
|
||||
],
|
||||
"expectations": [
|
||||
{
|
||||
"command_started_event": {
|
||||
"command": {
|
||||
"update": "test_bulkwrite_update_hint",
|
||||
"updates": [
|
||||
{
|
||||
"q": {
|
||||
"_id": {
|
||||
"$lt": 3
|
||||
}
|
||||
},
|
||||
"u": {
|
||||
"$inc": {
|
||||
"x": 1
|
||||
}
|
||||
},
|
||||
"multi": true,
|
||||
"hint": "_id_"
|
||||
},
|
||||
{
|
||||
"q": {
|
||||
"_id": {
|
||||
"$lt": 3
|
||||
}
|
||||
},
|
||||
"u": {
|
||||
"$inc": {
|
||||
"x": 1
|
||||
}
|
||||
},
|
||||
"multi": true,
|
||||
"hint": {
|
||||
"_id": 1
|
||||
}
|
||||
}
|
||||
],
|
||||
"ordered": true
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"outcome": {
|
||||
"collection": {
|
||||
"data": [
|
||||
{
|
||||
"_id": 1,
|
||||
"x": 13
|
||||
},
|
||||
{
|
||||
"_id": 2,
|
||||
"x": 24
|
||||
},
|
||||
{
|
||||
"_id": 3,
|
||||
"x": 33
|
||||
},
|
||||
{
|
||||
"_id": 4,
|
||||
"x": 44
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "BulkWrite replaceOne with update hints",
|
||||
"operations": [
|
||||
{
|
||||
"name": "bulkWrite",
|
||||
"arguments": {
|
||||
"requests": [
|
||||
{
|
||||
"name": "replaceOne",
|
||||
"arguments": {
|
||||
"filter": {
|
||||
"_id": 3
|
||||
},
|
||||
"replacement": {
|
||||
"x": 333
|
||||
},
|
||||
"hint": "_id_"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "replaceOne",
|
||||
"arguments": {
|
||||
"filter": {
|
||||
"_id": 4
|
||||
},
|
||||
"replacement": {
|
||||
"x": 444
|
||||
},
|
||||
"hint": {
|
||||
"_id": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"options": {
|
||||
"ordered": true
|
||||
}
|
||||
},
|
||||
"result": {
|
||||
"deletedCount": 0,
|
||||
"insertedCount": 0,
|
||||
"insertedIds": {},
|
||||
"matchedCount": 2,
|
||||
"modifiedCount": 2,
|
||||
"upsertedCount": 0,
|
||||
"upsertedIds": {}
|
||||
}
|
||||
}
|
||||
],
|
||||
"expectations": [
|
||||
{
|
||||
"command_started_event": {
|
||||
"command": {
|
||||
"update": "test_bulkwrite_update_hint",
|
||||
"updates": [
|
||||
{
|
||||
"q": {
|
||||
"_id": 3
|
||||
},
|
||||
"u": {
|
||||
"x": 333
|
||||
},
|
||||
"hint": "_id_"
|
||||
},
|
||||
{
|
||||
"q": {
|
||||
"_id": 4
|
||||
},
|
||||
"u": {
|
||||
"x": 444
|
||||
},
|
||||
"hint": {
|
||||
"_id": 1
|
||||
}
|
||||
}
|
||||
],
|
||||
"ordered": true
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"outcome": {
|
||||
"collection": {
|
||||
"data": [
|
||||
{
|
||||
"_id": 1,
|
||||
"x": 11
|
||||
},
|
||||
{
|
||||
"_id": 2,
|
||||
"x": 22
|
||||
},
|
||||
{
|
||||
"_id": 3,
|
||||
"x": 333
|
||||
},
|
||||
{
|
||||
"_id": 4,
|
||||
"x": 444
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
128
test/crud/v2/findOneAndReplace-hint.json
Normal file
128
test/crud/v2/findOneAndReplace-hint.json
Normal file
@ -0,0 +1,128 @@
|
||||
{
|
||||
"runOn": [
|
||||
{
|
||||
"minServerVersion": "4.3.1"
|
||||
}
|
||||
],
|
||||
"data": [
|
||||
{
|
||||
"_id": 1,
|
||||
"x": 11
|
||||
},
|
||||
{
|
||||
"_id": 2,
|
||||
"x": 22
|
||||
}
|
||||
],
|
||||
"collection_name": "findOneAndReplace_hint",
|
||||
"tests": [
|
||||
{
|
||||
"description": "FindOneAndReplace with hint string",
|
||||
"operations": [
|
||||
{
|
||||
"object": "collection",
|
||||
"name": "findOneAndReplace",
|
||||
"arguments": {
|
||||
"filter": {
|
||||
"_id": 1
|
||||
},
|
||||
"replacement": {
|
||||
"x": 33
|
||||
},
|
||||
"hint": "_id_"
|
||||
},
|
||||
"result": {
|
||||
"_id": 1,
|
||||
"x": 11
|
||||
}
|
||||
}
|
||||
],
|
||||
"expectations": [
|
||||
{
|
||||
"command_started_event": {
|
||||
"command": {
|
||||
"findAndModify": "findOneAndReplace_hint",
|
||||
"query": {
|
||||
"_id": 1
|
||||
},
|
||||
"update": {
|
||||
"x": 33
|
||||
},
|
||||
"hint": "_id_"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"outcome": {
|
||||
"collection": {
|
||||
"data": [
|
||||
{
|
||||
"_id": 1,
|
||||
"x": 33
|
||||
},
|
||||
{
|
||||
"_id": 2,
|
||||
"x": 22
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "FindOneAndReplace with hint document",
|
||||
"operations": [
|
||||
{
|
||||
"object": "collection",
|
||||
"name": "findOneAndReplace",
|
||||
"arguments": {
|
||||
"filter": {
|
||||
"_id": 1
|
||||
},
|
||||
"replacement": {
|
||||
"x": 33
|
||||
},
|
||||
"hint": {
|
||||
"_id": 1
|
||||
}
|
||||
},
|
||||
"result": {
|
||||
"_id": 1,
|
||||
"x": 11
|
||||
}
|
||||
}
|
||||
],
|
||||
"expectations": [
|
||||
{
|
||||
"command_started_event": {
|
||||
"command": {
|
||||
"findAndModify": "findOneAndReplace_hint",
|
||||
"query": {
|
||||
"_id": 1
|
||||
},
|
||||
"update": {
|
||||
"x": 33
|
||||
},
|
||||
"hint": {
|
||||
"_id": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"outcome": {
|
||||
"collection": {
|
||||
"data": [
|
||||
{
|
||||
"_id": 1,
|
||||
"x": 33
|
||||
},
|
||||
{
|
||||
"_id": 2,
|
||||
"x": 22
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
136
test/crud/v2/findOneAndUpdate-hint.json
Normal file
136
test/crud/v2/findOneAndUpdate-hint.json
Normal file
@ -0,0 +1,136 @@
|
||||
{
|
||||
"runOn": [
|
||||
{
|
||||
"minServerVersion": "4.3.1"
|
||||
}
|
||||
],
|
||||
"data": [
|
||||
{
|
||||
"_id": 1,
|
||||
"x": 11
|
||||
},
|
||||
{
|
||||
"_id": 2,
|
||||
"x": 22
|
||||
}
|
||||
],
|
||||
"collection_name": "findOneAndUpdate_hint",
|
||||
"tests": [
|
||||
{
|
||||
"description": "FindOneAndUpdate with hint string",
|
||||
"operations": [
|
||||
{
|
||||
"object": "collection",
|
||||
"name": "findOneAndUpdate",
|
||||
"arguments": {
|
||||
"filter": {
|
||||
"_id": 1
|
||||
},
|
||||
"update": {
|
||||
"$inc": {
|
||||
"x": 1
|
||||
}
|
||||
},
|
||||
"hint": "_id_"
|
||||
},
|
||||
"result": {
|
||||
"_id": 1,
|
||||
"x": 11
|
||||
}
|
||||
}
|
||||
],
|
||||
"expectations": [
|
||||
{
|
||||
"command_started_event": {
|
||||
"command": {
|
||||
"findAndModify": "findOneAndUpdate_hint",
|
||||
"query": {
|
||||
"_id": 1
|
||||
},
|
||||
"update": {
|
||||
"$inc": {
|
||||
"x": 1
|
||||
}
|
||||
},
|
||||
"hint": "_id_"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"outcome": {
|
||||
"collection": {
|
||||
"data": [
|
||||
{
|
||||
"_id": 1,
|
||||
"x": 12
|
||||
},
|
||||
{
|
||||
"_id": 2,
|
||||
"x": 22
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "FindOneAndUpdate with hint document",
|
||||
"operations": [
|
||||
{
|
||||
"object": "collection",
|
||||
"name": "findOneAndUpdate",
|
||||
"arguments": {
|
||||
"filter": {
|
||||
"_id": 1
|
||||
},
|
||||
"update": {
|
||||
"$inc": {
|
||||
"x": 1
|
||||
}
|
||||
},
|
||||
"hint": {
|
||||
"_id": 1
|
||||
}
|
||||
},
|
||||
"result": {
|
||||
"_id": 1,
|
||||
"x": 11
|
||||
}
|
||||
}
|
||||
],
|
||||
"expectations": [
|
||||
{
|
||||
"command_started_event": {
|
||||
"command": {
|
||||
"findAndModify": "findOneAndUpdate_hint",
|
||||
"query": {
|
||||
"_id": 1
|
||||
},
|
||||
"update": {
|
||||
"$inc": {
|
||||
"x": 1
|
||||
}
|
||||
},
|
||||
"hint": {
|
||||
"_id": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"outcome": {
|
||||
"collection": {
|
||||
"data": [
|
||||
{
|
||||
"_id": 1,
|
||||
"x": 12
|
||||
},
|
||||
{
|
||||
"_id": 2,
|
||||
"x": 22
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
146
test/crud/v2/replaceOne-hint.json
Normal file
146
test/crud/v2/replaceOne-hint.json
Normal file
@ -0,0 +1,146 @@
|
||||
{
|
||||
"runOn": [
|
||||
{
|
||||
"minServerVersion": "4.2.0"
|
||||
}
|
||||
],
|
||||
"data": [
|
||||
{
|
||||
"_id": 1,
|
||||
"x": 11
|
||||
},
|
||||
{
|
||||
"_id": 2,
|
||||
"x": 22
|
||||
}
|
||||
],
|
||||
"collection_name": "test_replaceone_hint",
|
||||
"tests": [
|
||||
{
|
||||
"description": "ReplaceOne with hint string",
|
||||
"operations": [
|
||||
{
|
||||
"object": "collection",
|
||||
"name": "replaceOne",
|
||||
"arguments": {
|
||||
"filter": {
|
||||
"_id": {
|
||||
"$gt": 1
|
||||
}
|
||||
},
|
||||
"replacement": {
|
||||
"x": 111
|
||||
},
|
||||
"hint": "_id_"
|
||||
},
|
||||
"result": {
|
||||
"matchedCount": 1,
|
||||
"modifiedCount": 1,
|
||||
"upsertedCount": 0
|
||||
}
|
||||
}
|
||||
],
|
||||
"expectations": [
|
||||
{
|
||||
"command_started_event": {
|
||||
"command": {
|
||||
"update": "test_replaceone_hint",
|
||||
"updates": [
|
||||
{
|
||||
"q": {
|
||||
"_id": {
|
||||
"$gt": 1
|
||||
}
|
||||
},
|
||||
"u": {
|
||||
"x": 111
|
||||
},
|
||||
"hint": "_id_"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"outcome": {
|
||||
"collection": {
|
||||
"data": [
|
||||
{
|
||||
"_id": 1,
|
||||
"x": 11
|
||||
},
|
||||
{
|
||||
"_id": 2,
|
||||
"x": 111
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "ReplaceOne with hint document",
|
||||
"operations": [
|
||||
{
|
||||
"object": "collection",
|
||||
"name": "replaceOne",
|
||||
"arguments": {
|
||||
"filter": {
|
||||
"_id": {
|
||||
"$gt": 1
|
||||
}
|
||||
},
|
||||
"replacement": {
|
||||
"x": 111
|
||||
},
|
||||
"hint": {
|
||||
"_id": 1
|
||||
}
|
||||
},
|
||||
"result": {
|
||||
"matchedCount": 1,
|
||||
"modifiedCount": 1,
|
||||
"upsertedCount": 0
|
||||
}
|
||||
}
|
||||
],
|
||||
"expectations": [
|
||||
{
|
||||
"command_started_event": {
|
||||
"command": {
|
||||
"update": "test_replaceone_hint",
|
||||
"updates": [
|
||||
{
|
||||
"q": {
|
||||
"_id": {
|
||||
"$gt": 1
|
||||
}
|
||||
},
|
||||
"u": {
|
||||
"x": 111
|
||||
},
|
||||
"hint": {
|
||||
"_id": 1
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"outcome": {
|
||||
"collection": {
|
||||
"data": [
|
||||
{
|
||||
"_id": 1,
|
||||
"x": 11
|
||||
},
|
||||
{
|
||||
"_id": 2,
|
||||
"x": 111
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
168
test/crud/v2/updateMany-hint.json
Normal file
168
test/crud/v2/updateMany-hint.json
Normal file
@ -0,0 +1,168 @@
|
||||
{
|
||||
"runOn": [
|
||||
{
|
||||
"minServerVersion": "4.2.0"
|
||||
}
|
||||
],
|
||||
"data": [
|
||||
{
|
||||
"_id": 1,
|
||||
"x": 11
|
||||
},
|
||||
{
|
||||
"_id": 2,
|
||||
"x": 22
|
||||
},
|
||||
{
|
||||
"_id": 3,
|
||||
"x": 33
|
||||
}
|
||||
],
|
||||
"collection_name": "test_updatemany_hint",
|
||||
"tests": [
|
||||
{
|
||||
"description": "UpdateMany with hint string",
|
||||
"operations": [
|
||||
{
|
||||
"object": "collection",
|
||||
"name": "updateMany",
|
||||
"arguments": {
|
||||
"filter": {
|
||||
"_id": {
|
||||
"$gt": 1
|
||||
}
|
||||
},
|
||||
"update": {
|
||||
"$inc": {
|
||||
"x": 1
|
||||
}
|
||||
},
|
||||
"hint": "_id_"
|
||||
},
|
||||
"result": {
|
||||
"matchedCount": 2,
|
||||
"modifiedCount": 2,
|
||||
"upsertedCount": 0
|
||||
}
|
||||
}
|
||||
],
|
||||
"expectations": [
|
||||
{
|
||||
"command_started_event": {
|
||||
"command": {
|
||||
"update": "test_updatemany_hint",
|
||||
"updates": [
|
||||
{
|
||||
"q": {
|
||||
"_id": {
|
||||
"$gt": 1
|
||||
}
|
||||
},
|
||||
"u": {
|
||||
"$inc": {
|
||||
"x": 1
|
||||
}
|
||||
},
|
||||
"multi": true,
|
||||
"hint": "_id_"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"outcome": {
|
||||
"collection": {
|
||||
"data": [
|
||||
{
|
||||
"_id": 1,
|
||||
"x": 11
|
||||
},
|
||||
{
|
||||
"_id": 2,
|
||||
"x": 23
|
||||
},
|
||||
{
|
||||
"_id": 3,
|
||||
"x": 34
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "UpdateMany with hint document",
|
||||
"operations": [
|
||||
{
|
||||
"object": "collection",
|
||||
"name": "updateMany",
|
||||
"arguments": {
|
||||
"filter": {
|
||||
"_id": {
|
||||
"$gt": 1
|
||||
}
|
||||
},
|
||||
"update": {
|
||||
"$inc": {
|
||||
"x": 1
|
||||
}
|
||||
},
|
||||
"hint": {
|
||||
"_id": 1
|
||||
}
|
||||
},
|
||||
"result": {
|
||||
"matchedCount": 2,
|
||||
"modifiedCount": 2,
|
||||
"upsertedCount": 0
|
||||
}
|
||||
}
|
||||
],
|
||||
"expectations": [
|
||||
{
|
||||
"command_started_event": {
|
||||
"command": {
|
||||
"update": "test_updatemany_hint",
|
||||
"updates": [
|
||||
{
|
||||
"q": {
|
||||
"_id": {
|
||||
"$gt": 1
|
||||
}
|
||||
},
|
||||
"u": {
|
||||
"$inc": {
|
||||
"x": 1
|
||||
}
|
||||
},
|
||||
"multi": true,
|
||||
"hint": {
|
||||
"_id": 1
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"outcome": {
|
||||
"collection": {
|
||||
"data": [
|
||||
{
|
||||
"_id": 1,
|
||||
"x": 11
|
||||
},
|
||||
{
|
||||
"_id": 2,
|
||||
"x": 23
|
||||
},
|
||||
{
|
||||
"_id": 3,
|
||||
"x": 34
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
154
test/crud/v2/updateOne-hint.json
Normal file
154
test/crud/v2/updateOne-hint.json
Normal file
@ -0,0 +1,154 @@
|
||||
{
|
||||
"runOn": [
|
||||
{
|
||||
"minServerVersion": "4.2.0"
|
||||
}
|
||||
],
|
||||
"data": [
|
||||
{
|
||||
"_id": 1,
|
||||
"x": 11
|
||||
},
|
||||
{
|
||||
"_id": 2,
|
||||
"x": 22
|
||||
}
|
||||
],
|
||||
"collection_name": "test_updateone_hint",
|
||||
"tests": [
|
||||
{
|
||||
"description": "UpdateOne with hint string",
|
||||
"operations": [
|
||||
{
|
||||
"object": "collection",
|
||||
"name": "updateOne",
|
||||
"arguments": {
|
||||
"filter": {
|
||||
"_id": {
|
||||
"$gt": 1
|
||||
}
|
||||
},
|
||||
"update": {
|
||||
"$inc": {
|
||||
"x": 1
|
||||
}
|
||||
},
|
||||
"hint": "_id_"
|
||||
},
|
||||
"result": {
|
||||
"matchedCount": 1,
|
||||
"modifiedCount": 1,
|
||||
"upsertedCount": 0
|
||||
}
|
||||
}
|
||||
],
|
||||
"expectations": [
|
||||
{
|
||||
"command_started_event": {
|
||||
"command": {
|
||||
"update": "test_updateone_hint",
|
||||
"updates": [
|
||||
{
|
||||
"q": {
|
||||
"_id": {
|
||||
"$gt": 1
|
||||
}
|
||||
},
|
||||
"u": {
|
||||
"$inc": {
|
||||
"x": 1
|
||||
}
|
||||
},
|
||||
"hint": "_id_"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"outcome": {
|
||||
"collection": {
|
||||
"data": [
|
||||
{
|
||||
"_id": 1,
|
||||
"x": 11
|
||||
},
|
||||
{
|
||||
"_id": 2,
|
||||
"x": 23
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "UpdateOne with hint document",
|
||||
"operations": [
|
||||
{
|
||||
"object": "collection",
|
||||
"name": "updateOne",
|
||||
"arguments": {
|
||||
"filter": {
|
||||
"_id": {
|
||||
"$gt": 1
|
||||
}
|
||||
},
|
||||
"update": {
|
||||
"$inc": {
|
||||
"x": 1
|
||||
}
|
||||
},
|
||||
"hint": {
|
||||
"_id": 1
|
||||
}
|
||||
},
|
||||
"result": {
|
||||
"matchedCount": 1,
|
||||
"modifiedCount": 1,
|
||||
"upsertedCount": 0
|
||||
}
|
||||
}
|
||||
],
|
||||
"expectations": [
|
||||
{
|
||||
"command_started_event": {
|
||||
"command": {
|
||||
"update": "test_updateone_hint",
|
||||
"updates": [
|
||||
{
|
||||
"q": {
|
||||
"_id": {
|
||||
"$gt": 1
|
||||
}
|
||||
},
|
||||
"u": {
|
||||
"$inc": {
|
||||
"x": 1
|
||||
}
|
||||
},
|
||||
"hint": {
|
||||
"_id": 1
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"outcome": {
|
||||
"collection": {
|
||||
"data": [
|
||||
{
|
||||
"_id": 1,
|
||||
"x": 11
|
||||
},
|
||||
{
|
||||
"_id": 2,
|
||||
"x": 23
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -22,12 +22,13 @@ from bson import decode, encode
|
||||
from bson.binary import Binary, STANDARD
|
||||
from bson.codec_options import CodecOptions
|
||||
from bson.int64 import Int64
|
||||
from bson.py3compat import iteritems, abc, text_type
|
||||
from bson.py3compat import iteritems, abc, string_type, text_type
|
||||
from bson.son import SON
|
||||
|
||||
from gridfs import GridFSBucket
|
||||
|
||||
from pymongo import (client_session,
|
||||
helpers,
|
||||
operations)
|
||||
from pymongo.command_cursor import CommandCursor
|
||||
from pymongo.cursor import Cursor
|
||||
@ -204,6 +205,25 @@ class SpecRunner(IntegrationTest):
|
||||
if 'maxCommitTimeMS' in opts:
|
||||
opts['max_commit_time_ms'] = opts.pop('maxCommitTimeMS')
|
||||
|
||||
if 'hint' in opts:
|
||||
hint = opts.pop('hint')
|
||||
if not isinstance(hint, string_type):
|
||||
hint = list(iteritems(hint))
|
||||
opts['hint'] = hint
|
||||
|
||||
# Properly format 'hint' arguments for the Bulk API tests.
|
||||
if 'requests' in opts:
|
||||
reqs = opts.pop('requests')
|
||||
for req in reqs:
|
||||
args = req.pop('arguments')
|
||||
if 'hint' in args:
|
||||
hint = args.pop('hint')
|
||||
if not isinstance(hint, string_type):
|
||||
hint = list(iteritems(hint))
|
||||
args['hint'] = hint
|
||||
req['arguments'] = args
|
||||
opts['requests'] = reqs
|
||||
|
||||
return dict(opts)
|
||||
|
||||
def run_operation(self, sessions, collection, operation):
|
||||
|
||||
Loading…
Reference in New Issue
Block a user