results.py 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. # Copyright 2015-present MongoDB, Inc.
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. """Result class definitions."""
  15. from pymongo.errors import InvalidOperation
  16. class _WriteResult(object):
  17. """Base class for write result classes."""
  18. __slots__ = ("__acknowledged",)
  19. def __init__(self, acknowledged):
  20. self.__acknowledged = acknowledged
  21. def _raise_if_unacknowledged(self, property_name):
  22. """Raise an exception on property access if unacknowledged."""
  23. if not self.__acknowledged:
  24. raise InvalidOperation("A value for %s is not available when "
  25. "the write is unacknowledged. Check the "
  26. "acknowledged attribute to avoid this "
  27. "error." % (property_name,))
  28. @property
  29. def acknowledged(self):
  30. """Is this the result of an acknowledged write operation?
  31. The :attr:`acknowledged` attribute will be ``False`` when using
  32. ``WriteConcern(w=0)``, otherwise ``True``.
  33. .. note::
  34. If the :attr:`acknowledged` attribute is ``False`` all other
  35. attibutes of this class will raise
  36. :class:`~pymongo.errors.InvalidOperation` when accessed. Values for
  37. other attributes cannot be determined if the write operation was
  38. unacknowledged.
  39. .. seealso::
  40. :class:`~pymongo.write_concern.WriteConcern`
  41. """
  42. return self.__acknowledged
  43. class InsertOneResult(_WriteResult):
  44. """The return type for :meth:`~pymongo.collection.Collection.insert_one`.
  45. """
  46. __slots__ = ("__inserted_id", "__acknowledged")
  47. def __init__(self, inserted_id, acknowledged):
  48. self.__inserted_id = inserted_id
  49. super(InsertOneResult, self).__init__(acknowledged)
  50. @property
  51. def inserted_id(self):
  52. """The inserted document's _id."""
  53. return self.__inserted_id
  54. class InsertManyResult(_WriteResult):
  55. """The return type for :meth:`~pymongo.collection.Collection.insert_many`.
  56. """
  57. __slots__ = ("__inserted_ids", "__acknowledged")
  58. def __init__(self, inserted_ids, acknowledged):
  59. self.__inserted_ids = inserted_ids
  60. super(InsertManyResult, self).__init__(acknowledged)
  61. @property
  62. def inserted_ids(self):
  63. """A list of _ids of the inserted documents, in the order provided.
  64. .. note:: If ``False`` is passed for the `ordered` parameter to
  65. :meth:`~pymongo.collection.Collection.insert_many` the server
  66. may have inserted the documents in a different order than what
  67. is presented here.
  68. """
  69. return self.__inserted_ids
  70. class UpdateResult(_WriteResult):
  71. """The return type for :meth:`~pymongo.collection.Collection.update_one`,
  72. :meth:`~pymongo.collection.Collection.update_many`, and
  73. :meth:`~pymongo.collection.Collection.replace_one`.
  74. """
  75. __slots__ = ("__raw_result", "__acknowledged")
  76. def __init__(self, raw_result, acknowledged):
  77. self.__raw_result = raw_result
  78. super(UpdateResult, self).__init__(acknowledged)
  79. @property
  80. def raw_result(self):
  81. """The raw result document returned by the server."""
  82. return self.__raw_result
  83. @property
  84. def matched_count(self):
  85. """The number of documents matched for this update."""
  86. self._raise_if_unacknowledged("matched_count")
  87. if self.upserted_id is not None:
  88. return 0
  89. return self.__raw_result.get("n", 0)
  90. @property
  91. def modified_count(self):
  92. """The number of documents modified.
  93. .. note:: modified_count is only reported by MongoDB 2.6 and later.
  94. When connected to an earlier server version, or in certain mixed
  95. version sharding configurations, this attribute will be set to
  96. ``None``.
  97. """
  98. self._raise_if_unacknowledged("modified_count")
  99. return self.__raw_result.get("nModified")
  100. @property
  101. def upserted_id(self):
  102. """The _id of the inserted document if an upsert took place. Otherwise
  103. ``None``.
  104. """
  105. self._raise_if_unacknowledged("upserted_id")
  106. return self.__raw_result.get("upserted")
  107. class DeleteResult(_WriteResult):
  108. """The return type for :meth:`~pymongo.collection.Collection.delete_one`
  109. and :meth:`~pymongo.collection.Collection.delete_many`"""
  110. __slots__ = ("__raw_result", "__acknowledged")
  111. def __init__(self, raw_result, acknowledged):
  112. self.__raw_result = raw_result
  113. super(DeleteResult, self).__init__(acknowledged)
  114. @property
  115. def raw_result(self):
  116. """The raw result document returned by the server."""
  117. return self.__raw_result
  118. @property
  119. def deleted_count(self):
  120. """The number of documents deleted."""
  121. self._raise_if_unacknowledged("deleted_count")
  122. return self.__raw_result.get("n", 0)
  123. class BulkWriteResult(_WriteResult):
  124. """An object wrapper for bulk API write results."""
  125. __slots__ = ("__bulk_api_result", "__acknowledged")
  126. def __init__(self, bulk_api_result, acknowledged):
  127. """Create a BulkWriteResult instance.
  128. :Parameters:
  129. - `bulk_api_result`: A result dict from the bulk API
  130. - `acknowledged`: Was this write result acknowledged? If ``False``
  131. then all properties of this object will raise
  132. :exc:`~pymongo.errors.InvalidOperation`.
  133. """
  134. self.__bulk_api_result = bulk_api_result
  135. super(BulkWriteResult, self).__init__(acknowledged)
  136. @property
  137. def bulk_api_result(self):
  138. """The raw bulk API result."""
  139. return self.__bulk_api_result
  140. @property
  141. def inserted_count(self):
  142. """The number of documents inserted."""
  143. self._raise_if_unacknowledged("inserted_count")
  144. return self.__bulk_api_result.get("nInserted")
  145. @property
  146. def matched_count(self):
  147. """The number of documents matched for an update."""
  148. self._raise_if_unacknowledged("matched_count")
  149. return self.__bulk_api_result.get("nMatched")
  150. @property
  151. def modified_count(self):
  152. """The number of documents modified.
  153. .. note:: modified_count is only reported by MongoDB 2.6 and later.
  154. When connected to an earlier server version, or in certain mixed
  155. version sharding configurations, this attribute will be set to
  156. ``None``.
  157. """
  158. self._raise_if_unacknowledged("modified_count")
  159. return self.__bulk_api_result.get("nModified")
  160. @property
  161. def deleted_count(self):
  162. """The number of documents deleted."""
  163. self._raise_if_unacknowledged("deleted_count")
  164. return self.__bulk_api_result.get("nRemoved")
  165. @property
  166. def upserted_count(self):
  167. """The number of documents upserted."""
  168. self._raise_if_unacknowledged("upserted_count")
  169. return self.__bulk_api_result.get("nUpserted")
  170. @property
  171. def upserted_ids(self):
  172. """A map of operation index to the _id of the upserted document."""
  173. self._raise_if_unacknowledged("upserted_ids")
  174. if self.__bulk_api_result:
  175. return dict((upsert["index"], upsert["_id"])
  176. for upsert in self.bulk_api_result["upserted"])