sensu-plugins-mongodb-mrtrotl 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG.md +1 -0
- data/LICENSE +22 -0
- data/README.md +27 -0
- data/bin/check-mongodb-metric.rb +144 -0
- data/bin/check-mongodb-query-count.rb +267 -0
- data/bin/check-mongodb.py +1644 -0
- data/bin/check-mongodb.rb +5 -0
- data/bin/metrics-mongodb-replication.rb +254 -0
- data/bin/metrics-mongodb.rb +133 -0
- data/lib/bson/__init__.py +1347 -0
- data/lib/bson/__pycache__/__init__.cpython-310.pyc +0 -0
- data/lib/bson/__pycache__/_helpers.cpython-310.pyc +0 -0
- data/lib/bson/__pycache__/binary.cpython-310.pyc +0 -0
- data/lib/bson/__pycache__/code.cpython-310.pyc +0 -0
- data/lib/bson/__pycache__/codec_options.cpython-310.pyc +0 -0
- data/lib/bson/__pycache__/dbref.cpython-310.pyc +0 -0
- data/lib/bson/__pycache__/decimal128.cpython-310.pyc +0 -0
- data/lib/bson/__pycache__/errors.cpython-310.pyc +0 -0
- data/lib/bson/__pycache__/int64.cpython-310.pyc +0 -0
- data/lib/bson/__pycache__/json_util.cpython-310.pyc +0 -0
- data/lib/bson/__pycache__/max_key.cpython-310.pyc +0 -0
- data/lib/bson/__pycache__/min_key.cpython-310.pyc +0 -0
- data/lib/bson/__pycache__/objectid.cpython-310.pyc +0 -0
- data/lib/bson/__pycache__/raw_bson.cpython-310.pyc +0 -0
- data/lib/bson/__pycache__/regex.cpython-310.pyc +0 -0
- data/lib/bson/__pycache__/son.cpython-310.pyc +0 -0
- data/lib/bson/__pycache__/timestamp.cpython-310.pyc +0 -0
- data/lib/bson/__pycache__/tz_util.cpython-310.pyc +0 -0
- data/lib/bson/_cbson.cpython-310-x86_64-linux-gnu.so +0 -0
- data/lib/bson/_helpers.py +41 -0
- data/lib/bson/binary.py +364 -0
- data/lib/bson/code.py +101 -0
- data/lib/bson/codec_options.py +414 -0
- data/lib/bson/codec_options.pyi +100 -0
- data/lib/bson/dbref.py +133 -0
- data/lib/bson/decimal128.py +314 -0
- data/lib/bson/errors.py +35 -0
- data/lib/bson/int64.py +39 -0
- data/lib/bson/json_util.py +874 -0
- data/lib/bson/max_key.py +55 -0
- data/lib/bson/min_key.py +55 -0
- data/lib/bson/objectid.py +286 -0
- data/lib/bson/py.typed +2 -0
- data/lib/bson/raw_bson.py +175 -0
- data/lib/bson/regex.py +135 -0
- data/lib/bson/son.py +208 -0
- data/lib/bson/timestamp.py +124 -0
- data/lib/bson/tz_util.py +52 -0
- data/lib/gridfs/__init__.py +1015 -0
- data/lib/gridfs/__pycache__/__init__.cpython-310.pyc +0 -0
- data/lib/gridfs/__pycache__/errors.cpython-310.pyc +0 -0
- data/lib/gridfs/__pycache__/grid_file.cpython-310.pyc +0 -0
- data/lib/gridfs/errors.py +33 -0
- data/lib/gridfs/grid_file.py +907 -0
- data/lib/gridfs/py.typed +2 -0
- data/lib/pymongo/__init__.py +185 -0
- data/lib/pymongo/__pycache__/__init__.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/_csot.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/aggregation.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/auth.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/auth_aws.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/bulk.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/change_stream.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/client_options.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/client_session.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/collation.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/collection.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/command_cursor.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/common.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/compression_support.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/cursor.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/daemon.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/database.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/driver_info.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/encryption.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/encryption_options.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/errors.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/event_loggers.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/hello.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/helpers.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/max_staleness_selectors.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/message.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/mongo_client.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/monitor.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/monitoring.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/network.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/ocsp_cache.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/ocsp_support.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/operations.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/periodic_executor.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/pool.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/pyopenssl_context.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/read_concern.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/read_preferences.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/response.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/results.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/saslprep.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/server.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/server_api.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/server_description.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/server_selectors.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/server_type.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/settings.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/socket_checker.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/srv_resolver.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/ssl_context.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/ssl_support.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/topology.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/topology_description.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/typings.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/uri_parser.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/write_concern.cpython-310.pyc +0 -0
- data/lib/pymongo/_cmessage.cpython-310-x86_64-linux-gnu.so +0 -0
- data/lib/pymongo/_csot.py +118 -0
- data/lib/pymongo/aggregation.py +229 -0
- data/lib/pymongo/auth.py +549 -0
- data/lib/pymongo/auth_aws.py +94 -0
- data/lib/pymongo/bulk.py +513 -0
- data/lib/pymongo/change_stream.py +457 -0
- data/lib/pymongo/client_options.py +302 -0
- data/lib/pymongo/client_session.py +1112 -0
- data/lib/pymongo/collation.py +224 -0
- data/lib/pymongo/collection.py +3204 -0
- data/lib/pymongo/command_cursor.py +353 -0
- data/lib/pymongo/common.py +984 -0
- data/lib/pymongo/compression_support.py +149 -0
- data/lib/pymongo/cursor.py +1345 -0
- data/lib/pymongo/daemon.py +141 -0
- data/lib/pymongo/database.py +1202 -0
- data/lib/pymongo/driver_info.py +42 -0
- data/lib/pymongo/encryption.py +884 -0
- data/lib/pymongo/encryption_options.py +221 -0
- data/lib/pymongo/errors.py +365 -0
- data/lib/pymongo/event_loggers.py +221 -0
- data/lib/pymongo/hello.py +219 -0
- data/lib/pymongo/helpers.py +259 -0
- data/lib/pymongo/max_staleness_selectors.py +114 -0
- data/lib/pymongo/message.py +1440 -0
- data/lib/pymongo/mongo_client.py +2144 -0
- data/lib/pymongo/monitor.py +440 -0
- data/lib/pymongo/monitoring.py +1801 -0
- data/lib/pymongo/network.py +311 -0
- data/lib/pymongo/ocsp_cache.py +87 -0
- data/lib/pymongo/ocsp_support.py +372 -0
- data/lib/pymongo/operations.py +507 -0
- data/lib/pymongo/periodic_executor.py +183 -0
- data/lib/pymongo/pool.py +1660 -0
- data/lib/pymongo/py.typed +2 -0
- data/lib/pymongo/pyopenssl_context.py +383 -0
- data/lib/pymongo/read_concern.py +75 -0
- data/lib/pymongo/read_preferences.py +609 -0
- data/lib/pymongo/response.py +109 -0
- data/lib/pymongo/results.py +217 -0
- data/lib/pymongo/saslprep.py +113 -0
- data/lib/pymongo/server.py +247 -0
- data/lib/pymongo/server_api.py +170 -0
- data/lib/pymongo/server_description.py +285 -0
- data/lib/pymongo/server_selectors.py +153 -0
- data/lib/pymongo/server_type.py +32 -0
- data/lib/pymongo/settings.py +159 -0
- data/lib/pymongo/socket_checker.py +104 -0
- data/lib/pymongo/srv_resolver.py +126 -0
- data/lib/pymongo/ssl_context.py +39 -0
- data/lib/pymongo/ssl_support.py +99 -0
- data/lib/pymongo/topology.py +890 -0
- data/lib/pymongo/topology_description.py +639 -0
- data/lib/pymongo/typings.py +39 -0
- data/lib/pymongo/uri_parser.py +624 -0
- data/lib/pymongo/write_concern.py +129 -0
- data/lib/pymongo-4.2.0.dist-info/INSTALLER +1 -0
- data/lib/pymongo-4.2.0.dist-info/LICENSE +201 -0
- data/lib/pymongo-4.2.0.dist-info/METADATA +250 -0
- data/lib/pymongo-4.2.0.dist-info/RECORD +167 -0
- data/lib/pymongo-4.2.0.dist-info/REQUESTED +0 -0
- data/lib/pymongo-4.2.0.dist-info/WHEEL +6 -0
- data/lib/pymongo-4.2.0.dist-info/top_level.txt +3 -0
- data/lib/sensu-plugins-mongodb/metrics.rb +391 -0
- data/lib/sensu-plugins-mongodb/version.rb +9 -0
- data/lib/sensu-plugins-mongodb.rb +1 -0
- metadata +407 -0
@@ -0,0 +1,1202 @@
|
|
1
|
+
# Copyright 2009-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
|
+
|
15
|
+
"""Database level operations."""
|
16
|
+
from typing import (
|
17
|
+
TYPE_CHECKING,
|
18
|
+
Any,
|
19
|
+
Dict,
|
20
|
+
Generic,
|
21
|
+
List,
|
22
|
+
Mapping,
|
23
|
+
MutableMapping,
|
24
|
+
NoReturn,
|
25
|
+
Optional,
|
26
|
+
Sequence,
|
27
|
+
TypeVar,
|
28
|
+
Union,
|
29
|
+
cast,
|
30
|
+
)
|
31
|
+
|
32
|
+
from bson.codec_options import DEFAULT_CODEC_OPTIONS, CodecOptions
|
33
|
+
from bson.dbref import DBRef
|
34
|
+
from bson.son import SON
|
35
|
+
from bson.timestamp import Timestamp
|
36
|
+
from pymongo import _csot, common
|
37
|
+
from pymongo.aggregation import _DatabaseAggregationCommand
|
38
|
+
from pymongo.change_stream import DatabaseChangeStream
|
39
|
+
from pymongo.collection import Collection
|
40
|
+
from pymongo.command_cursor import CommandCursor
|
41
|
+
from pymongo.common import _ecc_coll_name, _ecoc_coll_name, _esc_coll_name
|
42
|
+
from pymongo.errors import CollectionInvalid, InvalidName
|
43
|
+
from pymongo.read_preferences import ReadPreference, _ServerMode
|
44
|
+
from pymongo.typings import _CollationIn, _DocumentType, _Pipeline
|
45
|
+
|
46
|
+
|
47
|
+
def _check_name(name):
|
48
|
+
"""Check if a database name is valid."""
|
49
|
+
if not name:
|
50
|
+
raise InvalidName("database name cannot be the empty string")
|
51
|
+
|
52
|
+
for invalid_char in [" ", ".", "$", "/", "\\", "\x00", '"']:
|
53
|
+
if invalid_char in name:
|
54
|
+
raise InvalidName("database names cannot contain the character %r" % invalid_char)
|
55
|
+
|
56
|
+
|
57
|
+
if TYPE_CHECKING:
|
58
|
+
import bson.codec_options
|
59
|
+
from pymongo.client_session import ClientSession
|
60
|
+
from pymongo.mongo_client import MongoClient
|
61
|
+
from pymongo.read_concern import ReadConcern
|
62
|
+
from pymongo.write_concern import WriteConcern
|
63
|
+
|
64
|
+
|
65
|
+
_CodecDocumentType = TypeVar("_CodecDocumentType", bound=Mapping[str, Any])
|
66
|
+
|
67
|
+
|
68
|
+
class Database(common.BaseObject, Generic[_DocumentType]):
|
69
|
+
"""A Mongo database."""
|
70
|
+
|
71
|
+
def __init__(
|
72
|
+
self,
|
73
|
+
client: "MongoClient[_DocumentType]",
|
74
|
+
name: str,
|
75
|
+
codec_options: Optional[CodecOptions] = None,
|
76
|
+
read_preference: Optional[_ServerMode] = None,
|
77
|
+
write_concern: Optional["WriteConcern"] = None,
|
78
|
+
read_concern: Optional["ReadConcern"] = None,
|
79
|
+
) -> None:
|
80
|
+
"""Get a database by client and name.
|
81
|
+
|
82
|
+
Raises :class:`TypeError` if `name` is not an instance of
|
83
|
+
:class:`basestring` (:class:`str` in python 3). Raises
|
84
|
+
:class:`~pymongo.errors.InvalidName` if `name` is not a valid
|
85
|
+
database name.
|
86
|
+
|
87
|
+
:Parameters:
|
88
|
+
- `client`: A :class:`~pymongo.mongo_client.MongoClient` instance.
|
89
|
+
- `name`: The database name.
|
90
|
+
- `codec_options` (optional): An instance of
|
91
|
+
:class:`~bson.codec_options.CodecOptions`. If ``None`` (the
|
92
|
+
default) client.codec_options is used.
|
93
|
+
- `read_preference` (optional): The read preference to use. If
|
94
|
+
``None`` (the default) client.read_preference is used.
|
95
|
+
- `write_concern` (optional): An instance of
|
96
|
+
:class:`~pymongo.write_concern.WriteConcern`. If ``None`` (the
|
97
|
+
default) client.write_concern is used.
|
98
|
+
- `read_concern` (optional): An instance of
|
99
|
+
:class:`~pymongo.read_concern.ReadConcern`. If ``None`` (the
|
100
|
+
default) client.read_concern is used.
|
101
|
+
|
102
|
+
.. seealso:: The MongoDB documentation on `databases <https://dochub.mongodb.org/core/databases>`_.
|
103
|
+
|
104
|
+
.. versionchanged:: 4.0
|
105
|
+
Removed the eval, system_js, error, last_status, previous_error,
|
106
|
+
reset_error_history, authenticate, logout, collection_names,
|
107
|
+
current_op, add_user, remove_user, profiling_level,
|
108
|
+
set_profiling_level, and profiling_info methods.
|
109
|
+
See the :ref:`pymongo4-migration-guide`.
|
110
|
+
|
111
|
+
.. versionchanged:: 3.2
|
112
|
+
Added the read_concern option.
|
113
|
+
|
114
|
+
.. versionchanged:: 3.0
|
115
|
+
Added the codec_options, read_preference, and write_concern options.
|
116
|
+
:class:`~pymongo.database.Database` no longer returns an instance
|
117
|
+
of :class:`~pymongo.collection.Collection` for attribute names
|
118
|
+
with leading underscores. You must use dict-style lookups instead::
|
119
|
+
|
120
|
+
db['__my_collection__']
|
121
|
+
|
122
|
+
Not:
|
123
|
+
|
124
|
+
db.__my_collection__
|
125
|
+
"""
|
126
|
+
super(Database, self).__init__(
|
127
|
+
codec_options or client.codec_options,
|
128
|
+
read_preference or client.read_preference,
|
129
|
+
write_concern or client.write_concern,
|
130
|
+
read_concern or client.read_concern,
|
131
|
+
)
|
132
|
+
|
133
|
+
if not isinstance(name, str):
|
134
|
+
raise TypeError("name must be an instance of str")
|
135
|
+
|
136
|
+
if name != "$external":
|
137
|
+
_check_name(name)
|
138
|
+
|
139
|
+
self.__name = name
|
140
|
+
self.__client: MongoClient[_DocumentType] = client
|
141
|
+
self._timeout = client.options.timeout
|
142
|
+
|
143
|
+
@property
|
144
|
+
def client(self) -> "MongoClient[_DocumentType]":
|
145
|
+
"""The client instance for this :class:`Database`."""
|
146
|
+
return self.__client
|
147
|
+
|
148
|
+
@property
|
149
|
+
def name(self) -> str:
|
150
|
+
"""The name of this :class:`Database`."""
|
151
|
+
return self.__name
|
152
|
+
|
153
|
+
def with_options(
|
154
|
+
self,
|
155
|
+
codec_options: Optional[CodecOptions] = None,
|
156
|
+
read_preference: Optional[_ServerMode] = None,
|
157
|
+
write_concern: Optional["WriteConcern"] = None,
|
158
|
+
read_concern: Optional["ReadConcern"] = None,
|
159
|
+
) -> "Database[_DocumentType]":
|
160
|
+
"""Get a clone of this database changing the specified settings.
|
161
|
+
|
162
|
+
>>> db1.read_preference
|
163
|
+
Primary()
|
164
|
+
>>> from pymongo import ReadPreference
|
165
|
+
>>> db2 = db1.with_options(read_preference=ReadPreference.SECONDARY)
|
166
|
+
>>> db1.read_preference
|
167
|
+
Primary()
|
168
|
+
>>> db2.read_preference
|
169
|
+
Secondary(tag_sets=None)
|
170
|
+
|
171
|
+
:Parameters:
|
172
|
+
- `codec_options` (optional): An instance of
|
173
|
+
:class:`~bson.codec_options.CodecOptions`. If ``None`` (the
|
174
|
+
default) the :attr:`codec_options` of this :class:`Collection`
|
175
|
+
is used.
|
176
|
+
- `read_preference` (optional): The read preference to use. If
|
177
|
+
``None`` (the default) the :attr:`read_preference` of this
|
178
|
+
:class:`Collection` is used. See :mod:`~pymongo.read_preferences`
|
179
|
+
for options.
|
180
|
+
- `write_concern` (optional): An instance of
|
181
|
+
:class:`~pymongo.write_concern.WriteConcern`. If ``None`` (the
|
182
|
+
default) the :attr:`write_concern` of this :class:`Collection`
|
183
|
+
is used.
|
184
|
+
- `read_concern` (optional): An instance of
|
185
|
+
:class:`~pymongo.read_concern.ReadConcern`. If ``None`` (the
|
186
|
+
default) the :attr:`read_concern` of this :class:`Collection`
|
187
|
+
is used.
|
188
|
+
|
189
|
+
.. versionadded:: 3.8
|
190
|
+
"""
|
191
|
+
return Database(
|
192
|
+
self.client,
|
193
|
+
self.__name,
|
194
|
+
codec_options or self.codec_options,
|
195
|
+
read_preference or self.read_preference,
|
196
|
+
write_concern or self.write_concern,
|
197
|
+
read_concern or self.read_concern,
|
198
|
+
)
|
199
|
+
|
200
|
+
def __eq__(self, other: Any) -> bool:
|
201
|
+
if isinstance(other, Database):
|
202
|
+
return self.__client == other.client and self.__name == other.name
|
203
|
+
return NotImplemented
|
204
|
+
|
205
|
+
def __ne__(self, other: Any) -> bool:
|
206
|
+
return not self == other
|
207
|
+
|
208
|
+
def __hash__(self) -> int:
|
209
|
+
return hash((self.__client, self.__name))
|
210
|
+
|
211
|
+
def __repr__(self):
|
212
|
+
return "Database(%r, %r)" % (self.__client, self.__name)
|
213
|
+
|
214
|
+
def __getattr__(self, name: str) -> Collection[_DocumentType]:
|
215
|
+
"""Get a collection of this database by name.
|
216
|
+
|
217
|
+
Raises InvalidName if an invalid collection name is used.
|
218
|
+
|
219
|
+
:Parameters:
|
220
|
+
- `name`: the name of the collection to get
|
221
|
+
"""
|
222
|
+
if name.startswith("_"):
|
223
|
+
raise AttributeError(
|
224
|
+
"Database has no attribute %r. To access the %s"
|
225
|
+
" collection, use database[%r]." % (name, name, name)
|
226
|
+
)
|
227
|
+
return self.__getitem__(name)
|
228
|
+
|
229
|
+
def __getitem__(self, name: str) -> "Collection[_DocumentType]":
|
230
|
+
"""Get a collection of this database by name.
|
231
|
+
|
232
|
+
Raises InvalidName if an invalid collection name is used.
|
233
|
+
|
234
|
+
:Parameters:
|
235
|
+
- `name`: the name of the collection to get
|
236
|
+
"""
|
237
|
+
return Collection(self, name)
|
238
|
+
|
239
|
+
def get_collection(
|
240
|
+
self,
|
241
|
+
name: str,
|
242
|
+
codec_options: Optional[CodecOptions] = None,
|
243
|
+
read_preference: Optional[_ServerMode] = None,
|
244
|
+
write_concern: Optional["WriteConcern"] = None,
|
245
|
+
read_concern: Optional["ReadConcern"] = None,
|
246
|
+
) -> Collection[_DocumentType]:
|
247
|
+
"""Get a :class:`~pymongo.collection.Collection` with the given name
|
248
|
+
and options.
|
249
|
+
|
250
|
+
Useful for creating a :class:`~pymongo.collection.Collection` with
|
251
|
+
different codec options, read preference, and/or write concern from
|
252
|
+
this :class:`Database`.
|
253
|
+
|
254
|
+
>>> db.read_preference
|
255
|
+
Primary()
|
256
|
+
>>> coll1 = db.test
|
257
|
+
>>> coll1.read_preference
|
258
|
+
Primary()
|
259
|
+
>>> from pymongo import ReadPreference
|
260
|
+
>>> coll2 = db.get_collection(
|
261
|
+
... 'test', read_preference=ReadPreference.SECONDARY)
|
262
|
+
>>> coll2.read_preference
|
263
|
+
Secondary(tag_sets=None)
|
264
|
+
|
265
|
+
:Parameters:
|
266
|
+
- `name`: The name of the collection - a string.
|
267
|
+
- `codec_options` (optional): An instance of
|
268
|
+
:class:`~bson.codec_options.CodecOptions`. If ``None`` (the
|
269
|
+
default) the :attr:`codec_options` of this :class:`Database` is
|
270
|
+
used.
|
271
|
+
- `read_preference` (optional): The read preference to use. If
|
272
|
+
``None`` (the default) the :attr:`read_preference` of this
|
273
|
+
:class:`Database` is used. See :mod:`~pymongo.read_preferences`
|
274
|
+
for options.
|
275
|
+
- `write_concern` (optional): An instance of
|
276
|
+
:class:`~pymongo.write_concern.WriteConcern`. If ``None`` (the
|
277
|
+
default) the :attr:`write_concern` of this :class:`Database` is
|
278
|
+
used.
|
279
|
+
- `read_concern` (optional): An instance of
|
280
|
+
:class:`~pymongo.read_concern.ReadConcern`. If ``None`` (the
|
281
|
+
default) the :attr:`read_concern` of this :class:`Database` is
|
282
|
+
used.
|
283
|
+
"""
|
284
|
+
return Collection(
|
285
|
+
self,
|
286
|
+
name,
|
287
|
+
False,
|
288
|
+
codec_options,
|
289
|
+
read_preference,
|
290
|
+
write_concern,
|
291
|
+
read_concern,
|
292
|
+
)
|
293
|
+
|
294
|
+
@_csot.apply
|
295
|
+
def create_collection(
|
296
|
+
self,
|
297
|
+
name: str,
|
298
|
+
codec_options: Optional[CodecOptions] = None,
|
299
|
+
read_preference: Optional[_ServerMode] = None,
|
300
|
+
write_concern: Optional["WriteConcern"] = None,
|
301
|
+
read_concern: Optional["ReadConcern"] = None,
|
302
|
+
session: Optional["ClientSession"] = None,
|
303
|
+
check_exists: Optional[bool] = True,
|
304
|
+
**kwargs: Any,
|
305
|
+
) -> Collection[_DocumentType]:
|
306
|
+
"""Create a new :class:`~pymongo.collection.Collection` in this
|
307
|
+
database.
|
308
|
+
|
309
|
+
Normally collection creation is automatic. This method should
|
310
|
+
only be used to specify options on
|
311
|
+
creation. :class:`~pymongo.errors.CollectionInvalid` will be
|
312
|
+
raised if the collection already exists.
|
313
|
+
|
314
|
+
:Parameters:
|
315
|
+
- `name`: the name of the collection to create
|
316
|
+
- `codec_options` (optional): An instance of
|
317
|
+
:class:`~bson.codec_options.CodecOptions`. If ``None`` (the
|
318
|
+
default) the :attr:`codec_options` of this :class:`Database` is
|
319
|
+
used.
|
320
|
+
- `read_preference` (optional): The read preference to use. If
|
321
|
+
``None`` (the default) the :attr:`read_preference` of this
|
322
|
+
:class:`Database` is used.
|
323
|
+
- `write_concern` (optional): An instance of
|
324
|
+
:class:`~pymongo.write_concern.WriteConcern`. If ``None`` (the
|
325
|
+
default) the :attr:`write_concern` of this :class:`Database` is
|
326
|
+
used.
|
327
|
+
- `read_concern` (optional): An instance of
|
328
|
+
:class:`~pymongo.read_concern.ReadConcern`. If ``None`` (the
|
329
|
+
default) the :attr:`read_concern` of this :class:`Database` is
|
330
|
+
used.
|
331
|
+
- `collation` (optional): An instance of
|
332
|
+
:class:`~pymongo.collation.Collation`.
|
333
|
+
- `session` (optional): a
|
334
|
+
:class:`~pymongo.client_session.ClientSession`.
|
335
|
+
- ``check_exists`` (optional): if True (the default), send a listCollections command to
|
336
|
+
check if the collection already exists before creation.
|
337
|
+
- `**kwargs` (optional): additional keyword arguments will
|
338
|
+
be passed as options for the `create collection command`_
|
339
|
+
|
340
|
+
All optional `create collection command`_ parameters should be passed
|
341
|
+
as keyword arguments to this method. Valid options include, but are not
|
342
|
+
limited to:
|
343
|
+
|
344
|
+
- ``size`` (int): desired initial size for the collection (in
|
345
|
+
bytes). For capped collections this size is the max
|
346
|
+
size of the collection.
|
347
|
+
- ``capped`` (bool): if True, this is a capped collection
|
348
|
+
- ``max`` (int): maximum number of objects if capped (optional)
|
349
|
+
- ``timeseries`` (dict): a document specifying configuration options for
|
350
|
+
timeseries collections
|
351
|
+
- ``expireAfterSeconds`` (int): the number of seconds after which a
|
352
|
+
document in a timeseries collection expires
|
353
|
+
- ``validator`` (dict): a document specifying validation rules or expressions
|
354
|
+
for the collection
|
355
|
+
- ``validationLevel`` (str): how strictly to apply the
|
356
|
+
validation rules to existing documents during an update. The default level
|
357
|
+
is "strict"
|
358
|
+
- ``validationAction`` (str): whether to "error" on invalid documents
|
359
|
+
(the default) or just "warn" about the violations but allow invalid
|
360
|
+
documents to be inserted
|
361
|
+
- ``indexOptionDefaults`` (dict): a document specifying a default configuration
|
362
|
+
for indexes when creating a collection
|
363
|
+
- ``viewOn`` (str): the name of the source collection or view from which
|
364
|
+
to create the view
|
365
|
+
- ``pipeline`` (list): a list of aggregation pipeline stages
|
366
|
+
- ``comment`` (str): a user-provided comment to attach to this command.
|
367
|
+
This option is only supported on MongoDB >= 4.4.
|
368
|
+
- ``encryptedFields`` (dict): **(BETA)** Document that describes the encrypted fields for
|
369
|
+
Queryable Encryption. For example::
|
370
|
+
|
371
|
+
{
|
372
|
+
"escCollection": "enxcol_.encryptedCollection.esc",
|
373
|
+
"eccCollection": "enxcol_.encryptedCollection.ecc",
|
374
|
+
"ecocCollection": "enxcol_.encryptedCollection.ecoc",
|
375
|
+
"fields": [
|
376
|
+
{
|
377
|
+
"path": "firstName",
|
378
|
+
"keyId": Binary.from_uuid(UUID('00000000-0000-0000-0000-000000000000')),
|
379
|
+
"bsonType": "string",
|
380
|
+
"queries": {"queryType": "equality"}
|
381
|
+
},
|
382
|
+
{
|
383
|
+
"path": "ssn",
|
384
|
+
"keyId": Binary.from_uuid(UUID('04104104-1041-0410-4104-104104104104')),
|
385
|
+
"bsonType": "string"
|
386
|
+
}
|
387
|
+
]
|
388
|
+
}
|
389
|
+
- ``clusteredIndex`` (dict): Document that specifies the clustered index
|
390
|
+
configuration. It must have the following form::
|
391
|
+
|
392
|
+
{
|
393
|
+
// key pattern must be {_id: 1}
|
394
|
+
key: <key pattern>, // required
|
395
|
+
unique: <bool>, // required, must be ‘true’
|
396
|
+
name: <string>, // optional, otherwise automatically generated
|
397
|
+
v: <int>, // optional, must be ‘2’ if provided
|
398
|
+
}
|
399
|
+
- ``changeStreamPreAndPostImages`` (dict): a document with a boolean field ``enabled`` for
|
400
|
+
enabling pre- and post-images.
|
401
|
+
|
402
|
+
.. versionchanged:: 4.2
|
403
|
+
Added the ``check_exists``, ``clusteredIndex``, and ``encryptedFields`` parameters.
|
404
|
+
|
405
|
+
.. versionchanged:: 3.11
|
406
|
+
This method is now supported inside multi-document transactions
|
407
|
+
with MongoDB 4.4+.
|
408
|
+
|
409
|
+
.. versionchanged:: 3.6
|
410
|
+
Added ``session`` parameter.
|
411
|
+
|
412
|
+
.. versionchanged:: 3.4
|
413
|
+
Added the collation option.
|
414
|
+
|
415
|
+
.. versionchanged:: 3.0
|
416
|
+
Added the codec_options, read_preference, and write_concern options.
|
417
|
+
|
418
|
+
.. _create collection command:
|
419
|
+
https://mongodb.com/docs/manual/reference/command/create
|
420
|
+
"""
|
421
|
+
encrypted_fields = kwargs.get("encryptedFields")
|
422
|
+
if (
|
423
|
+
not encrypted_fields
|
424
|
+
and self.client.options.auto_encryption_opts
|
425
|
+
and self.client.options.auto_encryption_opts._encrypted_fields_map
|
426
|
+
):
|
427
|
+
encrypted_fields = self.client.options.auto_encryption_opts._encrypted_fields_map.get(
|
428
|
+
"%s.%s" % (self.name, name)
|
429
|
+
)
|
430
|
+
kwargs["encryptedFields"] = encrypted_fields
|
431
|
+
|
432
|
+
if encrypted_fields:
|
433
|
+
common.validate_is_mapping("encryptedFields", encrypted_fields)
|
434
|
+
|
435
|
+
clustered_index = kwargs.get("clusteredIndex")
|
436
|
+
if clustered_index:
|
437
|
+
common.validate_is_mapping("clusteredIndex", clustered_index)
|
438
|
+
|
439
|
+
with self.__client._tmp_session(session) as s:
|
440
|
+
# Skip this check in a transaction where listCollections is not
|
441
|
+
# supported.
|
442
|
+
if (
|
443
|
+
check_exists
|
444
|
+
and (not s or not s.in_transaction)
|
445
|
+
and name in self.list_collection_names(filter={"name": name}, session=s)
|
446
|
+
):
|
447
|
+
raise CollectionInvalid("collection %s already exists" % name)
|
448
|
+
return Collection(
|
449
|
+
self,
|
450
|
+
name,
|
451
|
+
True,
|
452
|
+
codec_options,
|
453
|
+
read_preference,
|
454
|
+
write_concern,
|
455
|
+
read_concern,
|
456
|
+
session=s,
|
457
|
+
**kwargs,
|
458
|
+
)
|
459
|
+
|
460
|
+
def aggregate(
|
461
|
+
self, pipeline: _Pipeline, session: Optional["ClientSession"] = None, **kwargs: Any
|
462
|
+
) -> CommandCursor[_DocumentType]:
|
463
|
+
"""Perform a database-level aggregation.
|
464
|
+
|
465
|
+
See the `aggregation pipeline`_ documentation for a list of stages
|
466
|
+
that are supported.
|
467
|
+
|
468
|
+
.. code-block:: python
|
469
|
+
|
470
|
+
# Lists all operations currently running on the server.
|
471
|
+
with client.admin.aggregate([{"$currentOp": {}}]) as cursor:
|
472
|
+
for operation in cursor:
|
473
|
+
print(operation)
|
474
|
+
|
475
|
+
The :meth:`aggregate` method obeys the :attr:`read_preference` of this
|
476
|
+
:class:`Database`, except when ``$out`` or ``$merge`` are used, in
|
477
|
+
which case :attr:`~pymongo.read_preferences.ReadPreference.PRIMARY`
|
478
|
+
is used.
|
479
|
+
|
480
|
+
.. note:: This method does not support the 'explain' option. Please
|
481
|
+
use :meth:`~pymongo.database.Database.command` instead.
|
482
|
+
|
483
|
+
.. note:: The :attr:`~pymongo.database.Database.write_concern` of
|
484
|
+
this collection is automatically applied to this operation.
|
485
|
+
|
486
|
+
:Parameters:
|
487
|
+
- `pipeline`: a list of aggregation pipeline stages
|
488
|
+
- `session` (optional): a
|
489
|
+
:class:`~pymongo.client_session.ClientSession`.
|
490
|
+
- `**kwargs` (optional): extra `aggregate command`_ parameters.
|
491
|
+
|
492
|
+
All optional `aggregate command`_ parameters should be passed as
|
493
|
+
keyword arguments to this method. Valid options include, but are not
|
494
|
+
limited to:
|
495
|
+
|
496
|
+
- `allowDiskUse` (bool): Enables writing to temporary files. When set
|
497
|
+
to True, aggregation stages can write data to the _tmp subdirectory
|
498
|
+
of the --dbpath directory. The default is False.
|
499
|
+
- `maxTimeMS` (int): The maximum amount of time to allow the operation
|
500
|
+
to run in milliseconds.
|
501
|
+
- `batchSize` (int): The maximum number of documents to return per
|
502
|
+
batch. Ignored if the connected mongod or mongos does not support
|
503
|
+
returning aggregate results using a cursor.
|
504
|
+
- `collation` (optional): An instance of
|
505
|
+
:class:`~pymongo.collation.Collation`.
|
506
|
+
- `let` (dict): A dict of parameter names and values. Values must be
|
507
|
+
constant or closed expressions that do not reference document
|
508
|
+
fields. Parameters can then be accessed as variables in an
|
509
|
+
aggregate expression context (e.g. ``"$$var"``). This option is
|
510
|
+
only supported on MongoDB >= 5.0.
|
511
|
+
|
512
|
+
:Returns:
|
513
|
+
A :class:`~pymongo.command_cursor.CommandCursor` over the result
|
514
|
+
set.
|
515
|
+
|
516
|
+
.. versionadded:: 3.9
|
517
|
+
|
518
|
+
.. _aggregation pipeline:
|
519
|
+
https://mongodb.com/docs/manual/reference/operator/aggregation-pipeline
|
520
|
+
|
521
|
+
.. _aggregate command:
|
522
|
+
https://mongodb.com/docs/manual/reference/command/aggregate
|
523
|
+
"""
|
524
|
+
with self.client._tmp_session(session, close=False) as s:
|
525
|
+
cmd = _DatabaseAggregationCommand(
|
526
|
+
self,
|
527
|
+
CommandCursor,
|
528
|
+
pipeline,
|
529
|
+
kwargs,
|
530
|
+
session is not None,
|
531
|
+
user_fields={"cursor": {"firstBatch": 1}},
|
532
|
+
)
|
533
|
+
return self.client._retryable_read(
|
534
|
+
cmd.get_cursor, cmd.get_read_preference(s), s, retryable=not cmd._performs_write
|
535
|
+
)
|
536
|
+
|
537
|
+
def watch(
|
538
|
+
self,
|
539
|
+
pipeline: Optional[_Pipeline] = None,
|
540
|
+
full_document: Optional[str] = None,
|
541
|
+
resume_after: Optional[Mapping[str, Any]] = None,
|
542
|
+
max_await_time_ms: Optional[int] = None,
|
543
|
+
batch_size: Optional[int] = None,
|
544
|
+
collation: Optional[_CollationIn] = None,
|
545
|
+
start_at_operation_time: Optional[Timestamp] = None,
|
546
|
+
session: Optional["ClientSession"] = None,
|
547
|
+
start_after: Optional[Mapping[str, Any]] = None,
|
548
|
+
comment: Optional[Any] = None,
|
549
|
+
full_document_before_change: Optional[str] = None,
|
550
|
+
) -> DatabaseChangeStream[_DocumentType]:
|
551
|
+
"""Watch changes on this database.
|
552
|
+
|
553
|
+
Performs an aggregation with an implicit initial ``$changeStream``
|
554
|
+
stage and returns a
|
555
|
+
:class:`~pymongo.change_stream.DatabaseChangeStream` cursor which
|
556
|
+
iterates over changes on all collections in this database.
|
557
|
+
|
558
|
+
Introduced in MongoDB 4.0.
|
559
|
+
|
560
|
+
.. code-block:: python
|
561
|
+
|
562
|
+
with db.watch() as stream:
|
563
|
+
for change in stream:
|
564
|
+
print(change)
|
565
|
+
|
566
|
+
The :class:`~pymongo.change_stream.DatabaseChangeStream` iterable
|
567
|
+
blocks until the next change document is returned or an error is
|
568
|
+
raised. If the
|
569
|
+
:meth:`~pymongo.change_stream.DatabaseChangeStream.next` method
|
570
|
+
encounters a network error when retrieving a batch from the server,
|
571
|
+
it will automatically attempt to recreate the cursor such that no
|
572
|
+
change events are missed. Any error encountered during the resume
|
573
|
+
attempt indicates there may be an outage and will be raised.
|
574
|
+
|
575
|
+
.. code-block:: python
|
576
|
+
|
577
|
+
try:
|
578
|
+
with db.watch(
|
579
|
+
[{'$match': {'operationType': 'insert'}}]) as stream:
|
580
|
+
for insert_change in stream:
|
581
|
+
print(insert_change)
|
582
|
+
except pymongo.errors.PyMongoError:
|
583
|
+
# The ChangeStream encountered an unrecoverable error or the
|
584
|
+
# resume attempt failed to recreate the cursor.
|
585
|
+
logging.error('...')
|
586
|
+
|
587
|
+
For a precise description of the resume process see the
|
588
|
+
`change streams specification`_.
|
589
|
+
|
590
|
+
:Parameters:
|
591
|
+
- `pipeline` (optional): A list of aggregation pipeline stages to
|
592
|
+
append to an initial ``$changeStream`` stage. Not all
|
593
|
+
pipeline stages are valid after a ``$changeStream`` stage, see the
|
594
|
+
MongoDB documentation on change streams for the supported stages.
|
595
|
+
- `full_document` (optional): The fullDocument to pass as an option
|
596
|
+
to the ``$changeStream`` stage. Allowed values: 'updateLookup',
|
597
|
+
'whenAvailable', 'required'. When set to 'updateLookup', the
|
598
|
+
change notification for partial updates will include both a delta
|
599
|
+
describing the changes to the document, as well as a copy of the
|
600
|
+
entire document that was changed from some time after the change
|
601
|
+
occurred.
|
602
|
+
- `full_document_before_change`: Allowed values: 'whenAvailable'
|
603
|
+
and 'required'. Change events may now result in a
|
604
|
+
'fullDocumentBeforeChange' response field.
|
605
|
+
- `resume_after` (optional): A resume token. If provided, the
|
606
|
+
change stream will start returning changes that occur directly
|
607
|
+
after the operation specified in the resume token. A resume token
|
608
|
+
is the _id value of a change document.
|
609
|
+
- `max_await_time_ms` (optional): The maximum time in milliseconds
|
610
|
+
for the server to wait for changes before responding to a getMore
|
611
|
+
operation.
|
612
|
+
- `batch_size` (optional): The maximum number of documents to return
|
613
|
+
per batch.
|
614
|
+
- `collation` (optional): The :class:`~pymongo.collation.Collation`
|
615
|
+
to use for the aggregation.
|
616
|
+
- `start_at_operation_time` (optional): If provided, the resulting
|
617
|
+
change stream will only return changes that occurred at or after
|
618
|
+
the specified :class:`~bson.timestamp.Timestamp`. Requires
|
619
|
+
MongoDB >= 4.0.
|
620
|
+
- `session` (optional): a
|
621
|
+
:class:`~pymongo.client_session.ClientSession`.
|
622
|
+
- `start_after` (optional): The same as `resume_after` except that
|
623
|
+
`start_after` can resume notifications after an invalidate event.
|
624
|
+
This option and `resume_after` are mutually exclusive.
|
625
|
+
- `comment` (optional): A user-provided comment to attach to this
|
626
|
+
command.
|
627
|
+
|
628
|
+
:Returns:
|
629
|
+
A :class:`~pymongo.change_stream.DatabaseChangeStream` cursor.
|
630
|
+
|
631
|
+
.. versionchanged:: 4.2
|
632
|
+
Added ``full_document_before_change`` parameter.
|
633
|
+
|
634
|
+
.. versionchanged:: 4.1
|
635
|
+
Added ``comment`` parameter.
|
636
|
+
|
637
|
+
.. versionchanged:: 3.9
|
638
|
+
Added the ``start_after`` parameter.
|
639
|
+
|
640
|
+
.. versionadded:: 3.7
|
641
|
+
|
642
|
+
.. seealso:: The MongoDB documentation on `changeStreams <https://mongodb.com/docs/manual/changeStreams/>`_.
|
643
|
+
|
644
|
+
.. _change streams specification:
|
645
|
+
https://github.com/mongodb/specifications/blob/master/source/change-streams/change-streams.rst
|
646
|
+
"""
|
647
|
+
return DatabaseChangeStream(
|
648
|
+
self,
|
649
|
+
pipeline,
|
650
|
+
full_document,
|
651
|
+
resume_after,
|
652
|
+
max_await_time_ms,
|
653
|
+
batch_size,
|
654
|
+
collation,
|
655
|
+
start_at_operation_time,
|
656
|
+
session,
|
657
|
+
start_after,
|
658
|
+
comment,
|
659
|
+
full_document_before_change,
|
660
|
+
)
|
661
|
+
|
662
|
+
def _command(
|
663
|
+
self,
|
664
|
+
sock_info,
|
665
|
+
command,
|
666
|
+
value=1,
|
667
|
+
check=True,
|
668
|
+
allowable_errors=None,
|
669
|
+
read_preference=ReadPreference.PRIMARY,
|
670
|
+
codec_options=DEFAULT_CODEC_OPTIONS,
|
671
|
+
write_concern=None,
|
672
|
+
parse_write_concern_error=False,
|
673
|
+
session=None,
|
674
|
+
**kwargs,
|
675
|
+
):
|
676
|
+
"""Internal command helper."""
|
677
|
+
if isinstance(command, str):
|
678
|
+
command = SON([(command, value)])
|
679
|
+
|
680
|
+
command.update(kwargs)
|
681
|
+
with self.__client._tmp_session(session) as s:
|
682
|
+
return sock_info.command(
|
683
|
+
self.__name,
|
684
|
+
command,
|
685
|
+
read_preference,
|
686
|
+
codec_options,
|
687
|
+
check,
|
688
|
+
allowable_errors,
|
689
|
+
write_concern=write_concern,
|
690
|
+
parse_write_concern_error=parse_write_concern_error,
|
691
|
+
session=s,
|
692
|
+
client=self.__client,
|
693
|
+
)
|
694
|
+
|
695
|
+
@_csot.apply
|
696
|
+
def command(
|
697
|
+
self,
|
698
|
+
command: Union[str, MutableMapping[str, Any]],
|
699
|
+
value: Any = 1,
|
700
|
+
check: bool = True,
|
701
|
+
allowable_errors: Optional[Sequence[Union[str, int]]] = None,
|
702
|
+
read_preference: Optional[_ServerMode] = None,
|
703
|
+
codec_options: "Optional[bson.codec_options.CodecOptions[_CodecDocumentType]]" = None,
|
704
|
+
session: Optional["ClientSession"] = None,
|
705
|
+
comment: Optional[Any] = None,
|
706
|
+
**kwargs: Any,
|
707
|
+
) -> _CodecDocumentType:
|
708
|
+
"""Issue a MongoDB command.
|
709
|
+
|
710
|
+
Send command `command` to the database and return the
|
711
|
+
response. If `command` is an instance of :class:`basestring`
|
712
|
+
(:class:`str` in python 3) then the command {`command`: `value`}
|
713
|
+
will be sent. Otherwise, `command` must be an instance of
|
714
|
+
:class:`dict` and will be sent as is.
|
715
|
+
|
716
|
+
Any additional keyword arguments will be added to the final
|
717
|
+
command document before it is sent.
|
718
|
+
|
719
|
+
For example, a command like ``{buildinfo: 1}`` can be sent
|
720
|
+
using:
|
721
|
+
|
722
|
+
>>> db.command("buildinfo")
|
723
|
+
|
724
|
+
For a command where the value matters, like ``{collstats:
|
725
|
+
collection_name}`` we can do:
|
726
|
+
|
727
|
+
>>> db.command("collstats", collection_name)
|
728
|
+
|
729
|
+
For commands that take additional arguments we can use
|
730
|
+
kwargs. So ``{filemd5: object_id, root: file_root}`` becomes:
|
731
|
+
|
732
|
+
>>> db.command("filemd5", object_id, root=file_root)
|
733
|
+
|
734
|
+
:Parameters:
|
735
|
+
- `command`: document representing the command to be issued,
|
736
|
+
or the name of the command (for simple commands only).
|
737
|
+
|
738
|
+
.. note:: the order of keys in the `command` document is
|
739
|
+
significant (the "verb" must come first), so commands
|
740
|
+
which require multiple keys (e.g. `findandmodify`)
|
741
|
+
should use an instance of :class:`~bson.son.SON` or
|
742
|
+
a string and kwargs instead of a Python `dict`.
|
743
|
+
|
744
|
+
- `value` (optional): value to use for the command verb when
|
745
|
+
`command` is passed as a string
|
746
|
+
- `check` (optional): check the response for errors, raising
|
747
|
+
:class:`~pymongo.errors.OperationFailure` if there are any
|
748
|
+
- `allowable_errors`: if `check` is ``True``, error messages
|
749
|
+
in this list will be ignored by error-checking
|
750
|
+
- `read_preference` (optional): The read preference for this
|
751
|
+
operation. See :mod:`~pymongo.read_preferences` for options.
|
752
|
+
If the provided `session` is in a transaction, defaults to the
|
753
|
+
read preference configured for the transaction.
|
754
|
+
Otherwise, defaults to
|
755
|
+
:attr:`~pymongo.read_preferences.ReadPreference.PRIMARY`.
|
756
|
+
- `codec_options`: A :class:`~bson.codec_options.CodecOptions`
|
757
|
+
instance.
|
758
|
+
- `session` (optional): A
|
759
|
+
:class:`~pymongo.client_session.ClientSession`.
|
760
|
+
- `comment` (optional): A user-provided comment to attach to this
|
761
|
+
command.
|
762
|
+
- `**kwargs` (optional): additional keyword arguments will
|
763
|
+
be added to the command document before it is sent
|
764
|
+
|
765
|
+
|
766
|
+
.. note:: :meth:`command` does **not** obey this Database's
|
767
|
+
:attr:`read_preference` or :attr:`codec_options`. You must use the
|
768
|
+
``read_preference`` and ``codec_options`` parameters instead.
|
769
|
+
|
770
|
+
.. note:: :meth:`command` does **not** apply any custom TypeDecoders
|
771
|
+
when decoding the command response.
|
772
|
+
|
773
|
+
.. note:: If this client has been configured to use MongoDB Stable
|
774
|
+
API (see :ref:`versioned-api-ref`), then :meth:`command` will
|
775
|
+
automatically add API versioning options to the given command.
|
776
|
+
Explicitly adding API versioning options in the command and
|
777
|
+
declaring an API version on the client is not supported.
|
778
|
+
|
779
|
+
.. versionchanged:: 3.6
|
780
|
+
Added ``session`` parameter.
|
781
|
+
|
782
|
+
.. versionchanged:: 3.0
|
783
|
+
Removed the `as_class`, `fields`, `uuid_subtype`, `tag_sets`,
|
784
|
+
and `secondary_acceptable_latency_ms` option.
|
785
|
+
Removed `compile_re` option: PyMongo now always represents BSON
|
786
|
+
regular expressions as :class:`~bson.regex.Regex` objects. Use
|
787
|
+
:meth:`~bson.regex.Regex.try_compile` to attempt to convert from a
|
788
|
+
BSON regular expression to a Python regular expression object.
|
789
|
+
Added the ``codec_options`` parameter.
|
790
|
+
|
791
|
+
.. seealso:: The MongoDB documentation on `commands <https://dochub.mongodb.org/core/commands>`_.
|
792
|
+
"""
|
793
|
+
opts = codec_options or DEFAULT_CODEC_OPTIONS
|
794
|
+
if comment is not None:
|
795
|
+
kwargs["comment"] = comment
|
796
|
+
|
797
|
+
if read_preference is None:
|
798
|
+
read_preference = (session and session._txn_read_preference()) or ReadPreference.PRIMARY
|
799
|
+
with self.__client._socket_for_reads(read_preference, session) as (
|
800
|
+
sock_info,
|
801
|
+
read_preference,
|
802
|
+
):
|
803
|
+
return self._command(
|
804
|
+
sock_info,
|
805
|
+
command,
|
806
|
+
value,
|
807
|
+
check,
|
808
|
+
allowable_errors,
|
809
|
+
read_preference,
|
810
|
+
opts,
|
811
|
+
session=session,
|
812
|
+
**kwargs,
|
813
|
+
)
|
814
|
+
|
815
|
+
def _retryable_read_command(
|
816
|
+
self,
|
817
|
+
command,
|
818
|
+
value=1,
|
819
|
+
check=True,
|
820
|
+
allowable_errors=None,
|
821
|
+
read_preference=None,
|
822
|
+
codec_options=DEFAULT_CODEC_OPTIONS,
|
823
|
+
session=None,
|
824
|
+
**kwargs,
|
825
|
+
):
|
826
|
+
"""Same as command but used for retryable read commands."""
|
827
|
+
if read_preference is None:
|
828
|
+
read_preference = (session and session._txn_read_preference()) or ReadPreference.PRIMARY
|
829
|
+
|
830
|
+
def _cmd(session, server, sock_info, read_preference):
|
831
|
+
return self._command(
|
832
|
+
sock_info,
|
833
|
+
command,
|
834
|
+
value,
|
835
|
+
check,
|
836
|
+
allowable_errors,
|
837
|
+
read_preference,
|
838
|
+
codec_options,
|
839
|
+
session=session,
|
840
|
+
**kwargs,
|
841
|
+
)
|
842
|
+
|
843
|
+
return self.__client._retryable_read(_cmd, read_preference, session)
|
844
|
+
|
845
|
+
def _list_collections(self, sock_info, session, read_preference, **kwargs):
|
846
|
+
"""Internal listCollections helper."""
|
847
|
+
|
848
|
+
coll = self.get_collection("$cmd", read_preference=read_preference)
|
849
|
+
cmd = SON([("listCollections", 1), ("cursor", {})])
|
850
|
+
cmd.update(kwargs)
|
851
|
+
with self.__client._tmp_session(session, close=False) as tmp_session:
|
852
|
+
cursor = self._command(
|
853
|
+
sock_info, cmd, read_preference=read_preference, session=tmp_session
|
854
|
+
)["cursor"]
|
855
|
+
cmd_cursor = CommandCursor(
|
856
|
+
coll,
|
857
|
+
cursor,
|
858
|
+
sock_info.address,
|
859
|
+
session=tmp_session,
|
860
|
+
explicit_session=session is not None,
|
861
|
+
comment=cmd.get("comment"),
|
862
|
+
)
|
863
|
+
cmd_cursor._maybe_pin_connection(sock_info)
|
864
|
+
return cmd_cursor
|
865
|
+
|
866
|
+
def list_collections(
|
867
|
+
self,
|
868
|
+
session: Optional["ClientSession"] = None,
|
869
|
+
filter: Optional[Mapping[str, Any]] = None,
|
870
|
+
comment: Optional[Any] = None,
|
871
|
+
**kwargs: Any,
|
872
|
+
) -> CommandCursor[Dict[str, Any]]:
|
873
|
+
"""Get a cursor over the collections of this database.
|
874
|
+
|
875
|
+
:Parameters:
|
876
|
+
- `session` (optional): a
|
877
|
+
:class:`~pymongo.client_session.ClientSession`.
|
878
|
+
- `filter` (optional): A query document to filter the list of
|
879
|
+
collections returned from the listCollections command.
|
880
|
+
- `comment` (optional): A user-provided comment to attach to this
|
881
|
+
command.
|
882
|
+
- `**kwargs` (optional): Optional parameters of the
|
883
|
+
`listCollections command
|
884
|
+
<https://mongodb.com/docs/manual/reference/command/listCollections/>`_
|
885
|
+
can be passed as keyword arguments to this method. The supported
|
886
|
+
options differ by server version.
|
887
|
+
|
888
|
+
|
889
|
+
:Returns:
|
890
|
+
An instance of :class:`~pymongo.command_cursor.CommandCursor`.
|
891
|
+
|
892
|
+
.. versionadded:: 3.6
|
893
|
+
"""
|
894
|
+
if filter is not None:
|
895
|
+
kwargs["filter"] = filter
|
896
|
+
read_pref = (session and session._txn_read_preference()) or ReadPreference.PRIMARY
|
897
|
+
if comment is not None:
|
898
|
+
kwargs["comment"] = comment
|
899
|
+
|
900
|
+
def _cmd(session, server, sock_info, read_preference):
|
901
|
+
return self._list_collections(
|
902
|
+
sock_info, session, read_preference=read_preference, **kwargs
|
903
|
+
)
|
904
|
+
|
905
|
+
return self.__client._retryable_read(_cmd, read_pref, session)
|
906
|
+
|
907
|
+
def list_collection_names(
|
908
|
+
self,
|
909
|
+
session: Optional["ClientSession"] = None,
|
910
|
+
filter: Optional[Mapping[str, Any]] = None,
|
911
|
+
comment: Optional[Any] = None,
|
912
|
+
**kwargs: Any,
|
913
|
+
) -> List[str]:
|
914
|
+
"""Get a list of all the collection names in this database.
|
915
|
+
|
916
|
+
For example, to list all non-system collections::
|
917
|
+
|
918
|
+
filter = {"name": {"$regex": r"^(?!system\\.)"}}
|
919
|
+
db.list_collection_names(filter=filter)
|
920
|
+
|
921
|
+
:Parameters:
|
922
|
+
- `session` (optional): a
|
923
|
+
:class:`~pymongo.client_session.ClientSession`.
|
924
|
+
- `filter` (optional): A query document to filter the list of
|
925
|
+
collections returned from the listCollections command.
|
926
|
+
- `comment` (optional): A user-provided comment to attach to this
|
927
|
+
command.
|
928
|
+
- `**kwargs` (optional): Optional parameters of the
|
929
|
+
`listCollections command
|
930
|
+
<https://mongodb.com/docs/manual/reference/command/listCollections/>`_
|
931
|
+
can be passed as keyword arguments to this method. The supported
|
932
|
+
options differ by server version.
|
933
|
+
|
934
|
+
|
935
|
+
.. versionchanged:: 3.8
|
936
|
+
Added the ``filter`` and ``**kwargs`` parameters.
|
937
|
+
|
938
|
+
.. versionadded:: 3.6
|
939
|
+
"""
|
940
|
+
if comment is not None:
|
941
|
+
kwargs["comment"] = comment
|
942
|
+
if filter is None:
|
943
|
+
kwargs["nameOnly"] = True
|
944
|
+
|
945
|
+
else:
|
946
|
+
# The enumerate collections spec states that "drivers MUST NOT set
|
947
|
+
# nameOnly if a filter specifies any keys other than name."
|
948
|
+
common.validate_is_mapping("filter", filter)
|
949
|
+
kwargs["filter"] = filter
|
950
|
+
if not filter or (len(filter) == 1 and "name" in filter):
|
951
|
+
kwargs["nameOnly"] = True
|
952
|
+
|
953
|
+
return [result["name"] for result in self.list_collections(session=session, **kwargs)]
|
954
|
+
|
955
|
+
def _drop_helper(self, name, session=None, comment=None):
|
956
|
+
command = SON([("drop", name)])
|
957
|
+
if comment is not None:
|
958
|
+
command["comment"] = comment
|
959
|
+
|
960
|
+
with self.__client._socket_for_writes(session) as sock_info:
|
961
|
+
return self._command(
|
962
|
+
sock_info,
|
963
|
+
command,
|
964
|
+
allowable_errors=["ns not found", 26],
|
965
|
+
write_concern=self._write_concern_for(session),
|
966
|
+
parse_write_concern_error=True,
|
967
|
+
session=session,
|
968
|
+
)
|
969
|
+
|
970
|
+
@_csot.apply
|
971
|
+
def drop_collection(
|
972
|
+
self,
|
973
|
+
name_or_collection: Union[str, Collection],
|
974
|
+
session: Optional["ClientSession"] = None,
|
975
|
+
comment: Optional[Any] = None,
|
976
|
+
encrypted_fields: Optional[Mapping[str, Any]] = None,
|
977
|
+
) -> Dict[str, Any]:
|
978
|
+
"""Drop a collection.
|
979
|
+
|
980
|
+
:Parameters:
|
981
|
+
- `name_or_collection`: the name of a collection to drop or the
|
982
|
+
collection object itself
|
983
|
+
- `session` (optional): a
|
984
|
+
:class:`~pymongo.client_session.ClientSession`.
|
985
|
+
- `comment` (optional): A user-provided comment to attach to this
|
986
|
+
command.
|
987
|
+
- `encrypted_fields`: **(BETA)** Document that describes the encrypted fields for
|
988
|
+
Queryable Encryption. For example::
|
989
|
+
|
990
|
+
{
|
991
|
+
"escCollection": "enxcol_.encryptedCollection.esc",
|
992
|
+
"eccCollection": "enxcol_.encryptedCollection.ecc",
|
993
|
+
"ecocCollection": "enxcol_.encryptedCollection.ecoc",
|
994
|
+
"fields": [
|
995
|
+
{
|
996
|
+
"path": "firstName",
|
997
|
+
"keyId": Binary.from_uuid(UUID('00000000-0000-0000-0000-000000000000')),
|
998
|
+
"bsonType": "string",
|
999
|
+
"queries": {"queryType": "equality"}
|
1000
|
+
},
|
1001
|
+
{
|
1002
|
+
"path": "ssn",
|
1003
|
+
"keyId": Binary.from_uuid(UUID('04104104-1041-0410-4104-104104104104')),
|
1004
|
+
"bsonType": "string"
|
1005
|
+
}
|
1006
|
+
]
|
1007
|
+
|
1008
|
+
}
|
1009
|
+
|
1010
|
+
|
1011
|
+
.. note:: The :attr:`~pymongo.database.Database.write_concern` of
|
1012
|
+
this database is automatically applied to this operation.
|
1013
|
+
|
1014
|
+
.. versionchanged:: 4.2
|
1015
|
+
Added ``encrypted_fields`` parameter.
|
1016
|
+
|
1017
|
+
.. versionchanged:: 4.1
|
1018
|
+
Added ``comment`` parameter.
|
1019
|
+
|
1020
|
+
.. versionchanged:: 3.6
|
1021
|
+
Added ``session`` parameter.
|
1022
|
+
|
1023
|
+
.. versionchanged:: 3.4
|
1024
|
+
Apply this database's write concern automatically to this operation
|
1025
|
+
when connected to MongoDB >= 3.4.
|
1026
|
+
|
1027
|
+
"""
|
1028
|
+
name = name_or_collection
|
1029
|
+
if isinstance(name, Collection):
|
1030
|
+
name = name.name
|
1031
|
+
|
1032
|
+
if not isinstance(name, str):
|
1033
|
+
raise TypeError("name_or_collection must be an instance of str")
|
1034
|
+
full_name = "%s.%s" % (self.name, name)
|
1035
|
+
if (
|
1036
|
+
not encrypted_fields
|
1037
|
+
and self.client.options.auto_encryption_opts
|
1038
|
+
and self.client.options.auto_encryption_opts._encrypted_fields_map
|
1039
|
+
):
|
1040
|
+
encrypted_fields = self.client.options.auto_encryption_opts._encrypted_fields_map.get(
|
1041
|
+
full_name
|
1042
|
+
)
|
1043
|
+
if not encrypted_fields and self.client.options.auto_encryption_opts:
|
1044
|
+
colls = list(
|
1045
|
+
self.list_collections(filter={"name": name}, session=session, comment=comment)
|
1046
|
+
)
|
1047
|
+
if colls and colls[0]["options"].get("encryptedFields"):
|
1048
|
+
encrypted_fields = colls[0]["options"]["encryptedFields"]
|
1049
|
+
if encrypted_fields:
|
1050
|
+
common.validate_is_mapping("encrypted_fields", encrypted_fields)
|
1051
|
+
self._drop_helper(
|
1052
|
+
_esc_coll_name(encrypted_fields, name), session=session, comment=comment
|
1053
|
+
)
|
1054
|
+
self._drop_helper(
|
1055
|
+
_ecc_coll_name(encrypted_fields, name), session=session, comment=comment
|
1056
|
+
)
|
1057
|
+
self._drop_helper(
|
1058
|
+
_ecoc_coll_name(encrypted_fields, name), session=session, comment=comment
|
1059
|
+
)
|
1060
|
+
|
1061
|
+
return self._drop_helper(name, session, comment)
|
1062
|
+
|
1063
|
+
def validate_collection(
|
1064
|
+
self,
|
1065
|
+
name_or_collection: Union[str, Collection],
|
1066
|
+
scandata: bool = False,
|
1067
|
+
full: bool = False,
|
1068
|
+
session: Optional["ClientSession"] = None,
|
1069
|
+
background: Optional[bool] = None,
|
1070
|
+
comment: Optional[Any] = None,
|
1071
|
+
) -> Dict[str, Any]:
|
1072
|
+
"""Validate a collection.
|
1073
|
+
|
1074
|
+
Returns a dict of validation info. Raises CollectionInvalid if
|
1075
|
+
validation fails.
|
1076
|
+
|
1077
|
+
See also the MongoDB documentation on the `validate command`_.
|
1078
|
+
|
1079
|
+
:Parameters:
|
1080
|
+
- `name_or_collection`: A Collection object or the name of a
|
1081
|
+
collection to validate.
|
1082
|
+
- `scandata`: Do extra checks beyond checking the overall
|
1083
|
+
structure of the collection.
|
1084
|
+
- `full`: Have the server do a more thorough scan of the
|
1085
|
+
collection. Use with `scandata` for a thorough scan
|
1086
|
+
of the structure of the collection and the individual
|
1087
|
+
documents.
|
1088
|
+
- `session` (optional): a
|
1089
|
+
:class:`~pymongo.client_session.ClientSession`.
|
1090
|
+
- `background` (optional): A boolean flag that determines whether
|
1091
|
+
the command runs in the background. Requires MongoDB 4.4+.
|
1092
|
+
- `comment` (optional): A user-provided comment to attach to this
|
1093
|
+
command.
|
1094
|
+
|
1095
|
+
.. versionchanged:: 4.1
|
1096
|
+
Added ``comment`` parameter.
|
1097
|
+
|
1098
|
+
.. versionchanged:: 3.11
|
1099
|
+
Added ``background`` parameter.
|
1100
|
+
|
1101
|
+
.. versionchanged:: 3.6
|
1102
|
+
Added ``session`` parameter.
|
1103
|
+
|
1104
|
+
.. _validate command: https://mongodb.com/docs/manual/reference/command/validate/
|
1105
|
+
"""
|
1106
|
+
name = name_or_collection
|
1107
|
+
if isinstance(name, Collection):
|
1108
|
+
name = name.name
|
1109
|
+
|
1110
|
+
if not isinstance(name, str):
|
1111
|
+
raise TypeError("name_or_collection must be an instance of str or Collection")
|
1112
|
+
cmd = SON([("validate", name), ("scandata", scandata), ("full", full)])
|
1113
|
+
if comment is not None:
|
1114
|
+
cmd["comment"] = comment
|
1115
|
+
|
1116
|
+
if background is not None:
|
1117
|
+
cmd["background"] = background
|
1118
|
+
|
1119
|
+
result = cast(dict, self.command(cmd, session=session))
|
1120
|
+
|
1121
|
+
valid = True
|
1122
|
+
# Pre 1.9 results
|
1123
|
+
if "result" in result:
|
1124
|
+
info = result["result"]
|
1125
|
+
if info.find("exception") != -1 or info.find("corrupt") != -1:
|
1126
|
+
raise CollectionInvalid("%s invalid: %s" % (name, info))
|
1127
|
+
# Sharded results
|
1128
|
+
elif "raw" in result:
|
1129
|
+
for _, res in result["raw"].items():
|
1130
|
+
if "result" in res:
|
1131
|
+
info = res["result"]
|
1132
|
+
if info.find("exception") != -1 or info.find("corrupt") != -1:
|
1133
|
+
raise CollectionInvalid("%s invalid: %s" % (name, info))
|
1134
|
+
elif not res.get("valid", False):
|
1135
|
+
valid = False
|
1136
|
+
break
|
1137
|
+
# Post 1.9 non-sharded results.
|
1138
|
+
elif not result.get("valid", False):
|
1139
|
+
valid = False
|
1140
|
+
|
1141
|
+
if not valid:
|
1142
|
+
raise CollectionInvalid("%s invalid: %r" % (name, result))
|
1143
|
+
|
1144
|
+
return result
|
1145
|
+
|
1146
|
+
# See PYTHON-3084.
|
1147
|
+
__iter__ = None
|
1148
|
+
|
1149
|
+
def __next__(self) -> NoReturn:
|
1150
|
+
raise TypeError("'Database' object is not iterable")
|
1151
|
+
|
1152
|
+
next = __next__
|
1153
|
+
|
1154
|
+
def __bool__(self) -> NoReturn:
|
1155
|
+
raise NotImplementedError(
|
1156
|
+
"Database objects do not implement truth "
|
1157
|
+
"value testing or bool(). Please compare "
|
1158
|
+
"with None instead: database is not None"
|
1159
|
+
)
|
1160
|
+
|
1161
|
+
def dereference(
|
1162
|
+
self,
|
1163
|
+
dbref: DBRef,
|
1164
|
+
session: Optional["ClientSession"] = None,
|
1165
|
+
comment: Optional[Any] = None,
|
1166
|
+
**kwargs: Any,
|
1167
|
+
) -> Optional[_DocumentType]:
|
1168
|
+
"""Dereference a :class:`~bson.dbref.DBRef`, getting the
|
1169
|
+
document it points to.
|
1170
|
+
|
1171
|
+
Raises :class:`TypeError` if `dbref` is not an instance of
|
1172
|
+
:class:`~bson.dbref.DBRef`. Returns a document, or ``None`` if
|
1173
|
+
the reference does not point to a valid document. Raises
|
1174
|
+
:class:`ValueError` if `dbref` has a database specified that
|
1175
|
+
is different from the current database.
|
1176
|
+
|
1177
|
+
:Parameters:
|
1178
|
+
- `dbref`: the reference
|
1179
|
+
- `session` (optional): a
|
1180
|
+
:class:`~pymongo.client_session.ClientSession`.
|
1181
|
+
- `comment` (optional): A user-provided comment to attach to this
|
1182
|
+
command.
|
1183
|
+
- `**kwargs` (optional): any additional keyword arguments
|
1184
|
+
are the same as the arguments to
|
1185
|
+
:meth:`~pymongo.collection.Collection.find`.
|
1186
|
+
|
1187
|
+
|
1188
|
+
.. versionchanged:: 4.1
|
1189
|
+
Added ``comment`` parameter.
|
1190
|
+
.. versionchanged:: 3.6
|
1191
|
+
Added ``session`` parameter.
|
1192
|
+
"""
|
1193
|
+
if not isinstance(dbref, DBRef):
|
1194
|
+
raise TypeError("cannot dereference a %s" % type(dbref))
|
1195
|
+
if dbref.database is not None and dbref.database != self.__name:
|
1196
|
+
raise ValueError(
|
1197
|
+
"trying to dereference a DBRef that points to "
|
1198
|
+
"another database (%r not %r)" % (dbref.database, self.__name)
|
1199
|
+
)
|
1200
|
+
return self[dbref.collection].find_one(
|
1201
|
+
{"_id": dbref.id}, session=session, comment=comment, **kwargs
|
1202
|
+
)
|