PYTHON-821 - Implement delete_one and delete_many.
This commit is contained in:
parent
e7866dbd19
commit
4d6bdb1097
@ -36,6 +36,8 @@
|
||||
.. automethod:: replace_one
|
||||
.. automethod:: update_one
|
||||
.. automethod:: update_many
|
||||
.. automethod:: delete_one
|
||||
.. automethod:: delete_many
|
||||
.. automethod:: insert(doc_or_docs[, manipulate=True[, check_keys=True[, continue_on_error=False[, **kwargs]]]])
|
||||
.. automethod:: save(to_save[, manipulate=True[, check_keys=True[, **kwargs]]])
|
||||
.. automethod:: update(spec, document[, upsert=False[, manipulate=False[, multi=False[, check_keys=True[, **kwargs]]]]])
|
||||
|
||||
@ -37,7 +37,7 @@ from pymongo.helpers import _check_write_command_response, _command
|
||||
from pymongo.message import _INSERT, _UPDATE, _DELETE
|
||||
from pymongo.options import ReturnDocument, _WriteOp
|
||||
from pymongo.read_preferences import ReadPreference
|
||||
from pymongo.results import BulkWriteResult, InsertOneResult, UpdateResult
|
||||
from pymongo.results import *
|
||||
from pymongo.write_concern import WriteConcern
|
||||
|
||||
|
||||
@ -832,8 +832,38 @@ class Collection(common.BaseObject):
|
||||
spec_or_id = {}
|
||||
if not isinstance(spec_or_id, collections.Mapping):
|
||||
spec_or_id = {"_id": spec_or_id}
|
||||
write_concern = None
|
||||
if kwargs:
|
||||
write_concern = WriteConcern(**kwargs)
|
||||
return self.__delete(spec_or_id, multi, write_concern)
|
||||
|
||||
concern = kwargs or self.write_concern.document
|
||||
def delete_one(self, filter):
|
||||
"""Delete a single document matching the filter.
|
||||
|
||||
:Parameters:
|
||||
- `filter`: A query that matches the document to delete.
|
||||
:Returns:
|
||||
- An instance of :class:`~pymongo.results.DeleteResult`.
|
||||
"""
|
||||
return DeleteResult(self.__delete(filter, False),
|
||||
self.write_concern.acknowledged)
|
||||
|
||||
def delete_many(self, filter):
|
||||
"""Delete one or more documents matching the filter.
|
||||
|
||||
:Parameters:
|
||||
- `filter`: A query that matches the documents to delete.
|
||||
:Returns:
|
||||
- An instance of :class:`~pymongo.results.DeleteResult`.
|
||||
"""
|
||||
return DeleteResult(self.__delete(filter, True),
|
||||
self.write_concern.acknowledged)
|
||||
|
||||
def __delete(self, filter, multi, write_concern=None):
|
||||
"""Internal delete helper."""
|
||||
if not isinstance(filter, collections.Mapping):
|
||||
raise TypeError("filter must be a mapping type")
|
||||
concern = (write_concern or self.write_concern).document
|
||||
safe = concern.get("w") != 0
|
||||
|
||||
client = self.database.connection
|
||||
@ -843,7 +873,7 @@ class Collection(common.BaseObject):
|
||||
if concern:
|
||||
command['writeConcern'] = concern
|
||||
|
||||
docs = [SON([('q', spec_or_id), ('limit', int(not multi))])]
|
||||
docs = [SON([('q', filter), ('limit', int(not multi))])]
|
||||
|
||||
results = message._do_batched_write_command(
|
||||
self.database.name + '.$cmd', _DELETE, command,
|
||||
@ -856,7 +886,7 @@ class Collection(common.BaseObject):
|
||||
else:
|
||||
# Legacy OP_DELETE
|
||||
return client._send_message(
|
||||
message.delete(self.__full_name, spec_or_id, safe,
|
||||
message.delete(self.__full_name, filter, safe,
|
||||
concern, self.codec_options,
|
||||
int(not multi)), safe)
|
||||
|
||||
|
||||
@ -96,6 +96,28 @@ class UpdateResult(_WriteResult):
|
||||
return self.__raw_result.get("upserted")
|
||||
|
||||
|
||||
class DeleteResult(_WriteResult):
|
||||
"""The return type for :meth:`~pymongo.collection.Collection.delete_one`
|
||||
and :meth:`~pymongo.collection.Collection.delete_many`"""
|
||||
|
||||
__slots__ = ("__raw_result", "__acknowledged")
|
||||
|
||||
def __init__(self, raw_result, acknowledged):
|
||||
self.__raw_result = raw_result
|
||||
super(DeleteResult, self).__init__(acknowledged)
|
||||
|
||||
@property
|
||||
def raw_result(self):
|
||||
"""The raw result document returned by the server."""
|
||||
return self.__raw_result
|
||||
|
||||
@property
|
||||
def deleted_count(self):
|
||||
"""The number of documents deleted."""
|
||||
self._raise_if_unacknowledged("deleted_count")
|
||||
return self.__raw_result.get("n", 0)
|
||||
|
||||
|
||||
class BulkWriteResult(_WriteResult):
|
||||
"""An object wrapper for bulk API write results."""
|
||||
|
||||
|
||||
@ -48,7 +48,7 @@ from pymongo.errors import (ConfigurationError,
|
||||
WTimeoutError)
|
||||
from pymongo.options import ReturnDocument
|
||||
from pymongo.read_preferences import ReadPreference
|
||||
from pymongo.results import InsertOneResult, UpdateResult
|
||||
from pymongo.results import DeleteResult, InsertOneResult, UpdateResult
|
||||
from pymongo.son_manipulator import SONManipulator
|
||||
from pymongo.write_concern import WriteConcern
|
||||
from test.test_client import IntegrationTest
|
||||
@ -676,6 +676,55 @@ class TestCollection(IntegrationTest):
|
||||
self.db.test.remove()
|
||||
self.assertEqual(0, self.db.test.count())
|
||||
|
||||
def test_delete_one(self):
|
||||
self.db.test.drop()
|
||||
|
||||
self.db.test.insert_one({"x": 1})
|
||||
self.db.test.insert_one({"y": 1})
|
||||
self.db.test.insert_one({"z": 1})
|
||||
|
||||
result = self.db.test.delete_one({"x": 1})
|
||||
self.assertTrue(isinstance(result, DeleteResult))
|
||||
self.assertEqual(1, result.deleted_count)
|
||||
self.assertTrue(result.acknowledged)
|
||||
self.assertEqual(2, self.db.test.count())
|
||||
|
||||
result = self.db.test.delete_one({"y": 1})
|
||||
self.assertTrue(isinstance(result, DeleteResult))
|
||||
self.assertEqual(1, result.deleted_count)
|
||||
self.assertTrue(result.acknowledged)
|
||||
self.assertEqual(1, self.db.test.count())
|
||||
|
||||
db = self.db.connection.get_database(self.db.name,
|
||||
write_concern=WriteConcern(w=0))
|
||||
result = db.test.delete_one({"z": 1})
|
||||
self.assertTrue(isinstance(result, DeleteResult))
|
||||
self.assertRaises(InvalidOperation, lambda: result.deleted_count)
|
||||
self.assertFalse(result.acknowledged)
|
||||
self.assertEqual(0, self.db.test.count())
|
||||
|
||||
def test_delete_many(self):
|
||||
self.db.test.drop()
|
||||
|
||||
self.db.test.insert_one({"x": 1})
|
||||
self.db.test.insert_one({"x": 1})
|
||||
self.db.test.insert_one({"y": 1})
|
||||
self.db.test.insert_one({"y": 1})
|
||||
|
||||
result = self.db.test.delete_many({"x": 1})
|
||||
self.assertTrue(isinstance(result, DeleteResult))
|
||||
self.assertEqual(2, result.deleted_count)
|
||||
self.assertTrue(result.acknowledged)
|
||||
self.assertEqual(0, self.db.test.count({"x": 2}))
|
||||
|
||||
db = self.db.connection.get_database(self.db.name,
|
||||
write_concern=WriteConcern(w=0))
|
||||
result = db.test.delete_many({"y": 1})
|
||||
self.assertTrue(isinstance(result, DeleteResult))
|
||||
self.assertRaises(InvalidOperation, lambda: result.deleted_count)
|
||||
self.assertFalse(result.acknowledged)
|
||||
self.assertEqual(0, self.db.test.count())
|
||||
|
||||
def test_find_w_fields(self):
|
||||
db = self.db
|
||||
db.test.remove({})
|
||||
|
||||
Loading…
Reference in New Issue
Block a user