PYTHON-982 - Support bypassDocumentValidation

This commit is contained in:
aherlihy 2015-10-05 14:17:13 -04:00 committed by Bernie Hackett
parent bcf0d57df3
commit f5b44ea35f
4 changed files with 359 additions and 40 deletions

View File

@ -199,7 +199,7 @@ def _merge_command(run, full_result, results):
class _Bulk(object):
"""The private guts of the bulk write API.
"""
def __init__(self, collection, ordered):
def __init__(self, collection, ordered, bypass_document_validation):
"""Initialize a _Bulk instance.
"""
self.collection = collection
@ -208,6 +208,7 @@ class _Bulk(object):
self.name = "%s.%s" % (collection.database.name, collection.name)
self.namespace = collection.database.name + '.$cmd'
self.executed = False
self.bypass_doc_val = bypass_document_validation
def add_insert(self, document):
"""Add an insert document to the list of ops.
@ -289,6 +290,8 @@ class _Bulk(object):
('ordered', self.ordered)])
if write_concern.document:
cmd['writeConcern'] = write_concern.document
if self.bypass_doc_val and sock_info.max_wire_version >= 4:
cmd['bypassDocumentValidation'] = True
bwc = _BulkWriteContext(db_name, cmd, sock_info, op_id, listeners)
results = _do_batched_write_command(
@ -320,26 +323,30 @@ class _Bulk(object):
for run in generator:
try:
if run.op_type == _INSERT:
coll._insert(sock_info,
run.ops,
self.ordered,
write_concern=write_concern,
op_id=op_id)
coll._insert(
sock_info,
run.ops,
self.ordered,
write_concern=write_concern,
op_id=op_id,
bypass_doc_val=self.bypass_doc_val)
elif run.op_type == _UPDATE:
for operation in run.ops:
doc = operation['u']
check_keys = True
if doc and next(iter(doc)).startswith('$'):
check_keys = False
coll._update(sock_info,
operation['q'],
doc,
operation['upsert'],
check_keys,
operation['multi'],
write_concern=write_concern,
op_id=op_id,
ordered=self.ordered)
coll._update(
sock_info,
operation['q'],
doc,
operation['upsert'],
check_keys,
operation['multi'],
write_concern=write_concern,
op_id=op_id,
ordered=self.ordered,
bypass_doc_val=self.bypass_doc_val)
else:
for operation in run.ops:
coll._delete(sock_info,
@ -556,7 +563,8 @@ class BulkOperationBuilder(object):
__slots__ = '__bulk'
def __init__(self, collection, ordered=True):
def __init__(self, collection, ordered=True,
bypass_document_validation=False):
"""Initialize a new BulkOperationBuilder instance.
:Parameters:
@ -567,8 +575,17 @@ class BulkOperationBuilder(object):
in arbitrary order (possibly in parallel on the server), reporting
any errors that occurred after attempting all operations. Defaults
to ``True``.
- `bypass_document_validation`: (optional) If ``True``, allows the
write to opt-out of document level validation. Default is
``False``.
.. note:: `bypass_document_validation` requires server version
**>= 3.2**
.. versionchanged:: 3.2
Added bypass_document_validation support
"""
self.__bulk = _Bulk(collection, ordered)
self.__bulk = _Bulk(collection, ordered, bypass_document_validation)
def find(self, selector):
"""Specify selection criteria for bulk operations.

View File

@ -306,36 +306,59 @@ class Collection(common.BaseObject):
write_concern or self.write_concern,
read_concern or self.read_concern)
def initialize_unordered_bulk_op(self):
def initialize_unordered_bulk_op(self, bypass_document_validation=False):
"""Initialize an unordered batch of write operations.
Operations will be performed on the server in arbitrary order,
possibly in parallel. All operations will be attempted.
:Parameters:
- `bypass_document_validation`: (optional) If ``True``, allows the
write to opt-out of document level validation. Default is
``False``.
Returns a :class:`~pymongo.bulk.BulkOperationBuilder` instance.
See :ref:`unordered_bulk` for examples.
.. note:: `bypass_document_validation` requires server version
**>= 3.2**
.. versionchanged:: 3.2
Added bypass_document_validation support
.. versionadded:: 2.7
"""
return BulkOperationBuilder(self, ordered=False)
return BulkOperationBuilder(self, False, bypass_document_validation)
def initialize_ordered_bulk_op(self):
def initialize_ordered_bulk_op(self, bypass_document_validation=False):
"""Initialize an ordered batch of write operations.
Operations will be performed on the server serially, in the
order provided. If an error occurs all remaining operations
are aborted.
:Parameters:
- `bypass_document_validation`: (optional) If ``True``, allows the
write to opt-out of document level validation. Default is
``False``.
Returns a :class:`~pymongo.bulk.BulkOperationBuilder` instance.
See :ref:`ordered_bulk` for examples.
.. note:: `bypass_document_validation` requires server version
**>= 3.2**
.. versionchanged:: 3.2
Added bypass_document_validation support
.. versionadded:: 2.7
"""
return BulkOperationBuilder(self, ordered=True)
return BulkOperationBuilder(self, True, bypass_document_validation)
def bulk_write(self, requests, ordered=True):
def bulk_write(self, requests, ordered=True,
bypass_document_validation=False):
"""Send a batch of write operations to the server.
Requests are passed as a list of write operation instances (
@ -379,18 +402,27 @@ class Collection(common.BaseObject):
occurs all remaining operations are aborted. If ``False`` requests
will be performed on the server in arbitrary order, possibly in
parallel, and all operations will be attempted.
- `bypass_document_validation`: (optional) If ``True``, allows the
write to opt-out of document level validation. Default is
``False``.
:Returns:
An instance of :class:`~pymongo.results.BulkWriteResult`.
.. seealso:: :ref:`writes-and-ids`
.. note:: `bypass_document_validation` requires server version
**>= 3.2**
.. versionchanged:: 3.2
Added bypass_document_validation support
.. versionadded:: 3.0
"""
if not isinstance(requests, list):
raise TypeError("requests must be a list")
blk = _Bulk(self, ordered)
blk = _Bulk(self, ordered, bypass_document_validation)
for request in requests:
if not isinstance(request, _WriteOp):
raise TypeError("%r is not a valid request" % (request,))
@ -448,7 +480,7 @@ class Collection(common.BaseObject):
def _insert_one(
self, sock_info, doc, ordered,
check_keys, manipulate, write_concern, op_id):
check_keys, manipulate, write_concern, op_id, bypass_doc_val):
"""Internal helper for inserting a single document."""
if manipulate:
doc = self.__database._apply_incoming_manipulators(doc, self)
@ -465,6 +497,8 @@ class Collection(common.BaseObject):
command['writeConcern'] = concern
if sock_info.max_wire_version > 1 and acknowledged:
if bypass_doc_val and sock_info.max_wire_version >= 4:
command['bypassDocumentValidation'] = True
# Insert command.
result = sock_info.command(self.__database.name,
command,
@ -480,12 +514,13 @@ class Collection(common.BaseObject):
return doc.get('_id')
def _insert(self, sock_info, docs, ordered=True, check_keys=True,
manipulate=False, write_concern=None, op_id=None):
manipulate=False, write_concern=None, op_id=None,
bypass_doc_val=False):
"""Internal insert helper."""
if isinstance(docs, collections.MutableMapping):
return self._insert_one(
sock_info, docs, ordered,
check_keys, manipulate, write_concern, op_id)
check_keys, manipulate, write_concern, op_id, bypass_doc_val)
ids = []
@ -522,6 +557,8 @@ class Collection(common.BaseObject):
command['writeConcern'] = concern
if op_id is None:
op_id = message._randint()
if bypass_doc_val and sock_info.max_wire_version >= 4:
command['bypassDocumentValidation'] = True
bwc = message._BulkWriteContext(
self.database.name, command, sock_info, op_id,
self.database.client._event_listeners)
@ -538,7 +575,7 @@ class Collection(common.BaseObject):
self.codec_options, bwc)
return ids
def insert_one(self, document):
def insert_one(self, document, bypass_document_validation=False):
"""Insert a single document.
>>> db.test.count({'x': 1})
@ -553,22 +590,34 @@ class Collection(common.BaseObject):
- `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.
- `bypass_document_validation`: (optional) If ``True``, allows the
write to opt-out of document level validation. Default is
``False``.
:Returns:
- An instance of :class:`~pymongo.results.InsertOneResult`.
.. seealso:: :ref:`writes-and-ids`
.. note:: `bypass_document_validation` requires server version
**>= 3.2**
.. versionchanged:: 3.2
Added bypass_document_validation support
.. versionadded:: 3.0
"""
common.validate_is_mutable_mapping("document", document)
if "_id" not in document:
document["_id"] = ObjectId()
with self._socket_for_writes() as sock_info:
return InsertOneResult(self._insert(sock_info, document),
self.write_concern.acknowledged)
return InsertOneResult(
self._insert(sock_info, document,
bypass_doc_val=bypass_document_validation),
self.write_concern.acknowledged)
def insert_many(self, documents, ordered=True):
def insert_many(self, documents, ordered=True,
bypass_document_validation=False):
"""Insert an iterable of documents.
>>> db.test.count()
@ -586,12 +635,21 @@ class Collection(common.BaseObject):
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.
- `bypass_document_validation`: (optional) If ``True``, allows the
write to opt-out of document level validation. Default is
``False``.
:Returns:
An instance of :class:`~pymongo.results.InsertManyResult`.
.. seealso:: :ref:`writes-and-ids`
.. note:: `bypass_document_validation` requires server version
**>= 3.2**
.. versionchanged:: 3.2
Added bypass_document_validation support
.. versionadded:: 3.0
"""
if not isinstance(documents, collections.Iterable) or not documents:
@ -606,14 +664,15 @@ class Collection(common.BaseObject):
inserted_ids.append(document["_id"])
yield (message._INSERT, document)
blk = _Bulk(self, ordered)
blk = _Bulk(self, ordered, bypass_document_validation)
blk.ops = [doc for doc in gen()]
blk.execute(self.write_concern.document)
return InsertManyResult(inserted_ids, self.write_concern.acknowledged)
def _update(self, sock_info, criteria, document, upsert=False,
check_keys=True, multi=False, manipulate=False,
write_concern=None, op_id=None, ordered=True):
write_concern=None, op_id=None, ordered=True,
bypass_doc_val=False):
"""Internal update / replace helper."""
common.validate_boolean("upsert", upsert)
if manipulate:
@ -630,6 +689,8 @@ class Collection(common.BaseObject):
command['writeConcern'] = concern
if sock_info.max_wire_version > 1 and acknowledged:
# Update command.
if bypass_doc_val and sock_info.max_wire_version >= 4:
command['bypassDocumentValidation'] = True
# The command result has to be published for APM unmodified
# so we make a shallow copy here before adding updatedExisting.
@ -655,7 +716,8 @@ class Collection(common.BaseObject):
message.update, self.__full_name, upsert, multi, criteria,
document, acknowledged, concern, check_keys, self.codec_options)
def replace_one(self, filter, replacement, upsert=False):
def replace_one(self, filter, replacement, upsert=False,
bypass_document_validation=False):
"""Replace a single document matching the filter.
>>> for doc in db.test.find({}):
@ -690,19 +752,30 @@ class Collection(common.BaseObject):
- `replacement`: The new document.
- `upsert` (optional): If ``True``, perform an insert if no documents
match the filter.
- `bypass_document_validation`: (optional) If ``True``, allows the
write to opt-out of document level validation. Default is
``False``.
:Returns:
- An instance of :class:`~pymongo.results.UpdateResult`.
.. note:: `bypass_document_validation` requires server version
**>= 3.2**
.. versionchanged:: 3.2
Added bypass_document_validation support
.. versionadded:: 3.0
"""
common.validate_is_mapping("filter", filter)
common.validate_ok_for_replace(replacement)
with self._socket_for_writes() as sock_info:
result = self._update(sock_info, filter, replacement, upsert)
result = self._update(sock_info, filter, replacement, upsert,
bypass_doc_val=bypass_document_validation)
return UpdateResult(result, self.write_concern.acknowledged)
def update_one(self, filter, update, upsert=False):
def update_one(self, filter, update, upsert=False,
bypass_document_validation=False):
"""Update a single document matching the filter.
>>> for doc in db.test.find():
@ -728,20 +801,31 @@ class Collection(common.BaseObject):
- `update`: The modifications to apply.
- `upsert` (optional): If ``True``, perform an insert if no documents
match the filter.
- `bypass_document_validation`: (optional) If ``True``, allows the
write to opt-out of document level validation. Default is
``False``.
:Returns:
- An instance of :class:`~pymongo.results.UpdateResult`.
.. note:: `bypass_document_validation` requires server version
**>= 3.2**
.. versionchanged:: 3.2
Added bypass_document_validation support
.. versionadded:: 3.0
"""
common.validate_is_mapping("filter", filter)
common.validate_ok_for_update(update)
with self._socket_for_writes() as sock_info:
result = self._update(sock_info, filter, update,
upsert, check_keys=False)
result = self._update(sock_info, filter, update, upsert,
check_keys=False,
bypass_doc_val=bypass_document_validation)
return UpdateResult(result, self.write_concern.acknowledged)
def update_many(self, filter, update, upsert=False):
def update_many(self, filter, update, upsert=False,
bypass_document_validation=False):
"""Update one or more documents that match the filter.
>>> for doc in db.test.find():
@ -767,17 +851,27 @@ class Collection(common.BaseObject):
- `update`: The modifications to apply.
- `upsert` (optional): If ``True``, perform an insert if no documents
match the filter.
- `bypass_document_validation`: (optional) If ``True``, allows the
write to opt-out of document level validation. Default is
``False``.
:Returns:
- An instance of :class:`~pymongo.results.UpdateResult`.
.. note:: `bypass_document_validation` requires server version
**>= 3.2**
.. versionchanged:: 3.2
Added bypass_document_validation support
.. versionadded:: 3.0
"""
common.validate_is_mapping("filter", filter)
common.validate_ok_for_update(update)
with self._socket_for_writes() as sock_info:
result = self._update(sock_info, filter, update, upsert,
check_keys=False, multi=True)
check_keys=False, multi=True,
bypass_doc_val=bypass_document_validation)
return UpdateResult(result, self.write_concern.acknowledged)
def drop(self):

View File

@ -138,6 +138,42 @@ class TestBulk(BulkTestBase):
# No error.
bulk.find({})
@client_context.require_version_min(3, 1, 9, -1)
@client_context.require_no_auth
def test_bypass_document_validation_bulk_op(self):
# Test insert
self.coll.insert_one({"z": 0})
self.db.command(SON([("collMod", "test"),
("validator", {"z": {"$gte": 0}})]))
bulk = self.coll.initialize_ordered_bulk_op(
bypass_document_validation=False)
bulk.insert({"z": -1}) # error
self.assertRaises(BulkWriteError, bulk.execute)
self.assertEqual(0, self.coll.count({"z": -1}))
bulk = self.coll.initialize_ordered_bulk_op(
bypass_document_validation=True)
bulk.insert({"z": -1})
bulk.execute()
self.assertEqual(1, self.coll.count({"z": -1}))
self.coll.insert_one({"z": 0})
self.db.command(SON([("collMod", "test"),
("validator", {"z": {"$gte": 0}})]))
bulk = self.coll.initialize_unordered_bulk_op(
bypass_document_validation=False)
bulk.insert({"z": -1}) # error
self.assertRaises(BulkWriteError, bulk.execute)
self.assertEqual(1, self.coll.count({"z": -1}))
bulk = self.coll.initialize_unordered_bulk_op(
bypass_document_validation=True)
bulk.insert({"z": -1})
bulk.execute()
self.assertEqual(2, self.coll.count({"z": -1}))
self.coll.drop()
def test_insert(self):
expected = {
'nMatched': 0,

View File

@ -32,6 +32,7 @@ from bson.son import SON
from pymongo import (ASCENDING, DESCENDING, GEO2D,
GEOHAYSTACK, GEOSPHERE, HASHED, TEXT)
from pymongo import MongoClient, monitoring
from pymongo.bulk import BulkWriteError
from pymongo.collection import Collection, ReturnDocument
from pymongo.command_cursor import CommandCursor
from pymongo.cursor import CursorType
@ -42,7 +43,7 @@ from pymongo.errors import (DocumentTooLarge,
InvalidOperation,
OperationFailure)
from pymongo.message import _COMMAND_OVERHEAD
from pymongo.operations import IndexModel
from pymongo.operations import *
from pymongo.read_preferences import ReadPreference
from pymongo.results import (InsertOneResult,
InsertManyResult,
@ -726,6 +727,177 @@ class TestCollection(IntegrationTest):
self.assertRaises(
DocumentTooLarge, coll.delete_one, {'data': large})
@client_context.require_version_min(3, 1, 9, -1)
@client_context.require_no_auth
def test_insert_bypass_document_validation(self):
db = self.db
db.test.drop()
db.create_collection("test", validator={"a": {"$exists": True}})
# Test insert_one
self.assertRaises(OperationFailure, db.test.insert_one,
{"_id": 1, "x": 100})
result = db.test.insert_one({"_id": 1, "x": 100},
bypass_document_validation=True)
self.assertTrue(isinstance(result, InsertOneResult))
self.assertEqual(1, result.inserted_id)
result = db.test.insert_one({"_id":2, "a":0})
self.assertTrue(isinstance(result, InsertOneResult))
self.assertEqual(2, result.inserted_id)
# Test insert_many
docs = [{"_id": i, "x": 100 - i} for i in range(3, 100)]
self.assertRaises(OperationFailure, db.test.insert_many, docs)
result = db.test.insert_many(docs, bypass_document_validation=True)
self.assertTrue(isinstance(result, InsertManyResult))
self.assertTrue(97, 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({"x": doc["x"]}))
self.assertTrue(result.acknowledged)
docs = [{"_id": i, "a": 200 - i} for i in range(100, 200)]
result = db.test.insert_many(docs)
self.assertTrue(isinstance(result, InsertManyResult))
self.assertTrue(97, 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({"a": doc["a"]}))
self.assertTrue(result.acknowledged)
@client_context.require_version_min(3, 1, 9, -1)
@client_context.require_no_auth
def test_replace_bypass_document_validation(self):
db = self.db
db.test.drop()
db.create_collection("test", validator={"a": {"$exists": True}})
# Test replace_one
db.test.insert_one({"a": 101})
self.assertRaises(OperationFailure, db.test.replace_one,
{"a": 101}, {"y": 1})
self.assertEqual(0, db.test.count({"y": 1}))
self.assertEqual(1, db.test.count({"a": 101}))
db.test.replace_one({"a": 101}, {"y": 1},
bypass_document_validation=True)
self.assertEqual(0, db.test.count({"a": 101}))
self.assertEqual(1, db.test.count({"y": 1}))
db.test.replace_one({"y": 1}, {"a": 102})
self.assertEqual(0, db.test.count({"y": 1}))
self.assertEqual(0, db.test.count({"a": 101}))
self.assertEqual(1, db.test.count({"a": 102}))
db.test.insert_one({"y": 1}, bypass_document_validation=True)
self.assertRaises(OperationFailure, db.test.replace_one,
{"y": 1}, {"x": 101})
self.assertEqual(0, db.test.count({"x": 101}))
self.assertEqual(1, db.test.count({"y": 1}))
db.test.replace_one({"y": 1}, {"x": 101},
bypass_document_validation=True)
self.assertEqual(0, db.test.count({"y": 1}))
self.assertEqual(1, db.test.count({"x": 101}))
db.test.replace_one({"x": 101}, {"a": 103},
bypass_document_validation=False)
self.assertEqual(0, db.test.count({"x": 101}))
self.assertEqual(1, db.test.count({"a": 103}))
@client_context.require_version_min(3, 1, 9, -1)
@client_context.require_no_auth
def test_update_bypass_document_validation(self):
db = self.db
db.test.drop()
db.test.insert_one({"z": 5})
db.command(SON([("collMod", "test"),
("validator", {"z": {"$gte": 0}})]))
# Test update_one
self.assertRaises(OperationFailure, db.test.update_one,
{"z": 5}, {"$inc": {"z": -10}})
self.assertEqual(0, db.test.count({"z": -5}))
self.assertEqual(1, db.test.count({"z": 5}))
db.test.update_one({"z": 5}, {"$inc": {"z": -10}},
bypass_document_validation=True)
self.assertEqual(0, db.test.count({"z": 5}))
self.assertEqual(1, db.test.count({"z": -5}))
db.test.update_one({"z": -5}, {"$inc": {"z": 6}},
bypass_document_validation=False)
self.assertEqual(1, db.test.count({"z": 1}))
self.assertEqual(0, db.test.count({"z": -5}))
db.test.insert_one({"z": -10},
bypass_document_validation=True)
self.assertRaises(OperationFailure, db.test.update_one,
{"z": -10}, {"$inc": {"z": 1}})
self.assertEqual(0, db.test.count({"z": -9}))
self.assertEqual(1, db.test.count({"z": -10}))
db.test.update_one({"z": -10}, {"$inc": {"z": 1}},
bypass_document_validation=True)
self.assertEqual(1, db.test.count({"z": -9}))
self.assertEqual(0, db.test.count({"z": -10}))
db.test.update_one({"z": -9}, {"$inc": {"z": 9}},
bypass_document_validation=False)
self.assertEqual(0, db.test.count({"z": -9}))
self.assertEqual(1, db.test.count({"z": 0}))
# Test update_many
db.test.insert_many([{"z": i} for i in range(3, 101)])
db.test.insert_one({"y": 0},
bypass_document_validation=True)
self.assertRaises(OperationFailure, db.test.update_many, {},
{"$inc": {"z": -100}})
self.assertEqual(100, db.test.count({"z": {"$gte": 0}}))
self.assertEqual(0, db.test.count({"z": {"$lt": 0}}))
self.assertEqual(0, db.test.count({"y": 0, "z": -100}))
db.test.update_many({"z": {"$gte": 0}}, {"$inc": {"z": -100}},
bypass_document_validation=True)
self.assertEqual(0, db.test.count({"z": {"$gt": 0}}))
self.assertEqual(100, db.test.count({"z": {"$lte": 0}}))
db.test.update_many({"z": {"$gt": -50}}, {"$inc": {"z": 100}},
bypass_document_validation=False)
self.assertEqual(50, db.test.count({"z": {"$gt": 0}}))
self.assertEqual(50, db.test.count({"z": {"$lt": 0}}))
db.test.insert_many([{"z": -i} for i in range(50)],
bypass_document_validation=True)
self.assertRaises(OperationFailure, db.test.update_many,
{}, {"$inc": {"z": 1}})
self.assertEqual(100, db.test.count({"z": {"$lte": 0}}))
self.assertEqual(50, db.test.count({"z": {"$gt": 1}}))
db.test.update_many({"z": {"$gte": 0}}, {"$inc": {"z": -100}},
bypass_document_validation=True)
self.assertEqual(0, db.test.count({"z": {"$gt": 0}}))
self.assertEqual(150, db.test.count({"z": {"$lte": 0}}))
db.test.update_many({"z": {"$lte": 0}}, {"$inc": {"z": 100}},
bypass_document_validation=False)
self.assertEqual(150, db.test.count({"z": {"$gte": 0}}))
self.assertEqual(0, db.test.count({"z": {"$lt": 0}}))
@client_context.require_version_min(3, 1, 9, -1)
@client_context.require_no_auth
def test_bypass_document_validation_bulk_write(self):
db = self.db
db.test.drop()
db.create_collection("test", validator={"a": {"$gte": 0}})
ops = [InsertOne({"a": -10}),
InsertOne({"a": -11}),
InsertOne({"a": -12}),
UpdateOne({"a": {"$lte": -10}}, {"$inc": {"a": 1}}),
UpdateMany({"a": {"$lte": -10}}, {"$inc": {"a": 1}}),
ReplaceOne({"a": {"$lte": -10}}, {"a": -1})]
db.test.bulk_write(ops, bypass_document_validation=True)
self.assertEqual(3, db.test.count())
self.assertEqual(1, db.test.count({"a": -11}))
self.assertEqual(1, db.test.count({"a": -1}))
self.assertEqual(1, db.test.count({"a": -9}))
# Assert that the operations would fail without bypass_doc_val
for op in ops:
self.assertRaises(BulkWriteError, db.test.bulk_write, [op])
def test_find_by_default_dct(self):
db = self.db
db.test.insert_one({'foo': 'bar'})