PYTHON-821 - Implement delete_one and delete_many.

This commit is contained in:
Bernie Hackett 2015-02-12 11:04:58 -08:00
parent e7866dbd19
commit 4d6bdb1097
4 changed files with 108 additions and 5 deletions

View File

@ -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]]]]])

View File

@ -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)

View File

@ -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."""

View File

@ -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({})