PYTHON-821 - Implement insert_many

This commit is contained in:
Bernie Hackett 2015-02-12 16:28:46 -08:00
parent 4d6bdb1097
commit f9243f0ad9
3 changed files with 93 additions and 2 deletions

View File

@ -29,7 +29,7 @@ from bson.son import SON
from pymongo import (common,
helpers,
message)
from pymongo.bulk import (BulkOperationBuilder, _Bulk)
from pymongo.bulk import BulkOperationBuilder, _Bulk
from pymongo.command_cursor import CommandCursor
from pymongo.cursor import Cursor
from pymongo.errors import ConfigurationError, InvalidName, OperationFailure
@ -495,6 +495,39 @@ class Collection(common.BaseObject):
return InsertOneResult(self.__insert(document),
self.write_concern.acknowledged)
def insert_many(self, documents, ordered=True):
"""Insert a list of documents.
:Parameters:
- `documents`: A list of documents to insert.
- `ordered` (optional): If ``True`` (the default) documents will be
inserted on the server serially, in the order provided. If an error
occurs all remaining inserts are aborted. If ``False``, documents
will be inserted on the server in arbitrary order, possibly in
parallel, and all document inserts will be attempted.
:Returns:
An instance of :class:`~pymongo.results.InsertManyResult`.
"""
if not isinstance(documents, list) or not documents:
raise TypeError("documents must be a non-empty list")
inserted_ids = []
def gen():
"""A generator that validates documents and handles _ids."""
for document in documents:
if not isinstance(document, collections.MutableMapping):
raise TypeError("document must be a dict or other "
"subclass of collections.MutableMapping")
if "_id" not in document:
document["_id"] = ObjectId()
inserted_ids.append(document["_id"])
yield (_INSERT, document)
blk = _Bulk(self, ordered)
blk.ops = [doc for doc in gen()]
blk.execute(self.write_concern.document)
return InsertManyResult(inserted_ids, self.write_concern.acknowledged)
def __insert(self, docs, ordered=True,
check_keys=True, manipulate=False, write_concern=None):
"""Internal insert helper."""

View File

@ -52,6 +52,28 @@ class InsertOneResult(_WriteResult):
return self.__inserted_id
class InsertManyResult(_WriteResult):
"""The return type for :meth:`~pymongo.collection.Collection.insert_many`.
"""
__slots__ = ("__inserted_ids", "__acknowledged")
def __init__(self, inserted_ids, acknowledged):
self.__inserted_ids = inserted_ids
super(InsertManyResult, self).__init__(acknowledged)
@property
def inserted_ids(self):
"""A list of _ids of the inserted documents, in the order provided.
.. note:: If ``False`` is passed for the `ordered` parameter to
:meth:`~pymongo.collection.Collection.insert_many` the server
may have inserted the documents in a different order than what
is presented here.
"""
return self.__inserted_ids
class UpdateResult(_WriteResult):
"""The return type for :meth:`~pymongo.collection.Collection.update_one`
and :meth:`~pymongo.collection.Collection.update_many`"""

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 DeleteResult, InsertOneResult, UpdateResult
from pymongo.results import *
from pymongo.son_manipulator import SONManipulator
from pymongo.write_concern import WriteConcern
from test.test_client import IntegrationTest
@ -639,6 +639,42 @@ class TestCollection(IntegrationTest):
# The insert failed duplicate key...
self.assertEqual(2, db.test.count())
def test_insert_many(self):
db = self.db
db.test.drop()
docs = [{} for _ in range(5)]
result = db.test.insert_many(docs)
self.assertTrue(isinstance(result, InsertManyResult))
self.assertTrue(isinstance(result.inserted_ids, list))
self.assertEqual(5, len(result.inserted_ids))
for doc in docs:
_id = doc["_id"]
self.assertTrue(isinstance(_id, ObjectId))
self.assertTrue(_id in result.inserted_ids)
self.assertEqual(1, db.test.count({'_id': _id}))
self.assertTrue(result.acknowledged)
docs = [{"_id": i} for i in range(5)]
result = db.test.insert_many(docs)
self.assertTrue(isinstance(result, InsertManyResult))
self.assertTrue(isinstance(result.inserted_ids, list))
self.assertEqual(5, len(result.inserted_ids))
for doc in docs:
_id = doc["_id"]
self.assertTrue(isinstance(_id, int))
self.assertTrue(_id in result.inserted_ids)
self.assertEqual(1, db.test.count({"_id": _id}))
self.assertTrue(result.acknowledged)
db = db.connection.get_database(db.name,
write_concern=WriteConcern(w=0))
docs = [{} for _ in range(5)]
result = db.test.insert_many(docs)
self.assertTrue(isinstance(result, InsertManyResult))
self.assertFalse(result.acknowledged)
self.assertEqual(15, db.test.count())
def test_generator_insert(self):
db = self.db
db.test.remove({})