PYTHON-821 - Implement insert_one.
This commit is contained in:
parent
7416e6595c
commit
df4e5269b3
@ -16,6 +16,9 @@
|
||||
.. autodata:: pymongo.cursor.TAILABLE_AWAIT
|
||||
.. autodata:: pymongo.cursor.EXHAUST
|
||||
|
||||
.. autoclass:: pymongo.collection.InsertOneResult
|
||||
:members:
|
||||
|
||||
.. autoclass:: pymongo.collection.ReturnDocument
|
||||
|
||||
.. autoattribute:: Before
|
||||
@ -39,6 +42,7 @@
|
||||
.. autoattribute:: read_preference
|
||||
.. autoattribute:: write_concern
|
||||
.. automethod:: with_options
|
||||
.. automethod:: insert_one
|
||||
.. 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]]]]])
|
||||
|
||||
@ -231,7 +231,7 @@ class BulkWriteResult(object):
|
||||
|
||||
@property
|
||||
def acknowledged(self):
|
||||
"""Was this bulk write operation acknowledged?"""
|
||||
"""Is this the result of an acknowledged bulk write operation?"""
|
||||
return self.__acknowledged
|
||||
|
||||
@property
|
||||
|
||||
@ -39,6 +39,7 @@ from pymongo.errors import ConfigurationError, InvalidName, OperationFailure
|
||||
from pymongo.helpers import _check_write_command_response, _command
|
||||
from pymongo.message import _INSERT, _UPDATE, _DELETE
|
||||
from pymongo.read_preferences import ReadPreference
|
||||
from pymongo.write_concern import WriteConcern
|
||||
|
||||
|
||||
try:
|
||||
@ -50,6 +51,26 @@ except ImportError:
|
||||
_NO_OBJ_ERROR = "No matching object found"
|
||||
|
||||
|
||||
class InsertOneResult(object):
|
||||
"""The return type for :meth:`Collection.insert_one`."""
|
||||
|
||||
__slots__ = ("__inserted_id", "__acknowledged")
|
||||
|
||||
def __init__(self, inserted_id, acknowledged):
|
||||
self.__inserted_id = inserted_id
|
||||
self.__acknowledged = acknowledged
|
||||
|
||||
@property
|
||||
def inserted_id(self):
|
||||
"""The inserted document's _id."""
|
||||
return self.__inserted_id
|
||||
|
||||
@property
|
||||
def acknowledged(self):
|
||||
"""Is this the result of an acknowledged write operation?"""
|
||||
return self.__acknowledged
|
||||
|
||||
|
||||
class ReturnDocument(object):
|
||||
"""An enum used with :meth:`Collection.find_one_and_replace` and
|
||||
:meth:`Collection.find_one_and_update`.
|
||||
@ -483,8 +504,34 @@ class Collection(common.BaseObject):
|
||||
|
||||
.. mongodoc:: insert
|
||||
"""
|
||||
write_concern = None
|
||||
if kwargs:
|
||||
write_concern = WriteConcern(**kwargs)
|
||||
return self.__insert(doc_or_docs, not continue_on_error,
|
||||
check_keys, manipulate, write_concern)
|
||||
|
||||
def insert_one(self, document):
|
||||
"""Insert a single document.
|
||||
|
||||
:Parameters:
|
||||
- `document`: The document to insert. Must be a mutable mapping
|
||||
type. If the document does not have an _id field one will be
|
||||
added automatically.
|
||||
|
||||
:Returns:
|
||||
- An instance of :class:`InsertOneResult`.
|
||||
"""
|
||||
if not isinstance(document, collections.MutableMapping):
|
||||
raise TypeError("document must be a mutable mapping type")
|
||||
if "_id" not in document:
|
||||
document["_id"] = ObjectId()
|
||||
return InsertOneResult(self.__insert(document),
|
||||
self.write_concern.acknowledged)
|
||||
|
||||
def __insert(self, docs, ordered=True,
|
||||
check_keys=True, manipulate=False, write_concern=None):
|
||||
"""Internal insert helper."""
|
||||
client = self.database.connection
|
||||
docs = doc_or_docs
|
||||
return_one = False
|
||||
if isinstance(docs, collections.MutableMapping):
|
||||
return_one = True
|
||||
@ -512,13 +559,13 @@ class Collection(common.BaseObject):
|
||||
ids.append(doc.get('_id'))
|
||||
yield doc
|
||||
|
||||
concern = kwargs or self.write_concern.document
|
||||
concern = (write_concern or self.write_concern).document
|
||||
safe = concern.get("w") != 0
|
||||
|
||||
if client._writable_max_wire_version() > 1 and safe:
|
||||
# Insert command
|
||||
command = SON([('insert', self.name),
|
||||
('ordered', not continue_on_error)])
|
||||
('ordered', ordered)])
|
||||
|
||||
if concern:
|
||||
command['writeConcern'] = concern
|
||||
@ -530,9 +577,8 @@ class Collection(common.BaseObject):
|
||||
else:
|
||||
# Legacy batched OP_INSERT
|
||||
message._do_batched_insert(self.__full_name, gen(), check_keys,
|
||||
safe, concern, continue_on_error,
|
||||
safe, concern, not ordered,
|
||||
self.codec_options, client)
|
||||
|
||||
if return_one:
|
||||
return ids[0]
|
||||
else:
|
||||
|
||||
@ -35,10 +35,11 @@ from bson.son import SON
|
||||
from pymongo import (ASCENDING, DESCENDING, GEO2D,
|
||||
GEOHAYSTACK, GEOSPHERE, HASHED, TEXT)
|
||||
from pymongo import MongoClient
|
||||
from pymongo.collection import Collection, ReturnDocument
|
||||
from pymongo.collection import Collection, ReturnDocument, InsertOneResult
|
||||
from pymongo.command_cursor import CommandCursor
|
||||
from pymongo.cursor import EXHAUST
|
||||
from pymongo.errors import (DocumentTooLarge,
|
||||
from pymongo.errors import (ConfigurationError,
|
||||
DocumentTooLarge,
|
||||
DuplicateKeyError,
|
||||
InvalidDocument,
|
||||
InvalidName,
|
||||
@ -605,6 +606,37 @@ class TestCollection(IntegrationTest):
|
||||
qcheck.check_unittest(self, remove_insert_find_one,
|
||||
qcheck.gen_mongo_dict(3))
|
||||
|
||||
def test_insert_one(self):
|
||||
db = self.db
|
||||
db.test.drop()
|
||||
|
||||
document = {"_id": 1000}
|
||||
result = db.test.insert_one(document)
|
||||
self.assertTrue(isinstance(result, InsertOneResult))
|
||||
self.assertTrue(isinstance(result.inserted_id, int))
|
||||
self.assertEqual(document["_id"], result.inserted_id)
|
||||
self.assertTrue(result.acknowledged)
|
||||
self.assertIsNotNone(db.test.find_one({"_id": document["_id"]}))
|
||||
self.assertEqual(1, db.test.count())
|
||||
|
||||
document = {"foo": "bar"}
|
||||
result = db.test.insert_one(document)
|
||||
self.assertTrue(isinstance(result, InsertOneResult))
|
||||
self.assertTrue(isinstance(result.inserted_id, ObjectId))
|
||||
self.assertEqual(document["_id"], result.inserted_id)
|
||||
self.assertTrue(result.acknowledged)
|
||||
self.assertIsNotNone(db.test.find_one({"_id": document["_id"]}))
|
||||
|
||||
db = db.connection.get_database(db.name,
|
||||
write_concern=WriteConcern(w=0))
|
||||
result = db.test.insert_one(document)
|
||||
self.assertTrue(isinstance(result, InsertOneResult))
|
||||
self.assertTrue(isinstance(result.inserted_id, ObjectId))
|
||||
self.assertEqual(document["_id"], result.inserted_id)
|
||||
self.assertFalse(result.acknowledged)
|
||||
# The insert failed duplicate key...
|
||||
self.assertEqual(2, db.test.count())
|
||||
|
||||
def test_generator_insert(self):
|
||||
db = self.db
|
||||
db.test.remove({})
|
||||
@ -1231,7 +1263,7 @@ class TestCollection(IntegrationTest):
|
||||
wtimeout_err(coll.remove, {"x": 1}, w=w, wtimeout=1)
|
||||
|
||||
# can't use fsync and j options together
|
||||
self.assertRaises(OperationFailure, self.db.test.insert,
|
||||
self.assertRaises(ConfigurationError, self.db.test.insert,
|
||||
{"_id": 1}, j=True, fsync=True)
|
||||
|
||||
def test_manual_last_error(self):
|
||||
|
||||
Loading…
Reference in New Issue
Block a user