Skip to content

PYTHON-1323 Removed Collection.group #559

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 26, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion doc/api/pymongo/collection.rst
Original file line number Diff line number Diff line change
Expand Up @@ -69,5 +69,4 @@
.. automethod:: inline_map_reduce
.. automethod:: initialize_unordered_bulk_op
.. automethod:: initialize_ordered_bulk_op
.. automethod:: group
.. automethod:: count
1 change: 1 addition & 0 deletions doc/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ Breaking Changes in 4.0
- Removed :meth:`pymongo.collection.Collection.update`.
- Removed :meth:`pymongo.collection.Collection.remove`.
- Removed :meth:`pymongo.collection.Collection.find_and_modify`.
- Removed :meth:`pymongo.collection.Collection.group`.
- Removed :meth:`pymongo.mongo_client.MongoClient.close_cursor`. Use
:meth:`pymongo.cursor.Cursor.close` instead.
- Removed :meth:`pymongo.mongo_client.MongoClient.kill_cursors`.
Expand Down
10 changes: 10 additions & 0 deletions doc/migrate-to-pymongo4.rst
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,16 @@ Can be changed to this::
replaced_doc = collection.find_one_and_replace({'b': 1}, {'c': 1})
deleted_doc = collection.find_one_and_delete({'c': 1})

Collection.group is removed
...........................

Removed :meth:`pymongo.collection.Collection.group`. This method was
deprecated in PyMongo 3.5. MongoDB 4.2 removed the `group command`_.
Use :meth:`~pymongo.collection.Collection.aggregate` with the ``$group`` stage
instead.

.. _group command: https://docs.mongodb.com/manual/reference/command/group/

Collection.ensure_index is removed
..................................

Expand Down
40 changes: 0 additions & 40 deletions pymongo/collection.py
Original file line number Diff line number Diff line change
Expand Up @@ -2366,46 +2366,6 @@ def watch(self, pipeline=None, full_document=None, resume_after=None,
batch_size, collation, start_at_operation_time, session,
start_after)

def group(self, key, condition, initial, reduce, finalize=None, **kwargs):
"""Perform a query similar to an SQL *group by* operation.

**DEPRECATED** - The group command was deprecated in MongoDB 3.4. The
:meth:`~group` method is deprecated and will be removed in PyMongo 4.0.
Use :meth:`~aggregate` with the `$group` stage or :meth:`~map_reduce`
instead.

.. versionchanged:: 3.5
Deprecated the group method.
.. versionchanged:: 3.4
Added the `collation` option.
.. versionchanged:: 2.2
Removed deprecated argument: command
"""
warnings.warn("The group method is deprecated and will be removed in "
"PyMongo 4.0. Use the aggregate method with the $group "
"stage or the map_reduce method instead.",
DeprecationWarning, stacklevel=2)
group = {}
if isinstance(key, str):
group["$keyf"] = Code(key)
elif key is not None:
group = {"key": helpers._fields_list_to_dict(key, "key")}
group["ns"] = self.__name
group["$reduce"] = Code(reduce)
group["cond"] = condition
group["initial"] = initial
if finalize is not None:
group["finalize"] = Code(finalize)

cmd = SON([("group", group)])
collation = validate_collation_or_none(kwargs.pop('collation', None))
cmd.update(kwargs)

with self._socket_for_reads(session=None) as (sock_info, slave_ok):
return self._command(sock_info, cmd, slave_ok,
collation=collation,
user_fields={'retval': 1})["retval"]

def rename(self, new_name, session=None, **kwargs):
"""Rename this collection.

Expand Down
8 changes: 0 additions & 8 deletions test/test_collation.py
Original file line number Diff line number Diff line change
Expand Up @@ -188,14 +188,6 @@ def test_explain_command(self):
self.collation.document,
self.last_command_started()['explain']['collation'])

@raisesConfigurationErrorForOldMongoDB
@client_context.require_version_max(4, 1, 0, -1)
def test_group(self):
self.db.test.group('foo', {'foo': {'$gt': 42}}, {},
'function(a, b) { return a; }',
collation=self.collation)
self.assertCollationInLastCommand()

@raisesConfigurationErrorForOldMongoDB
def test_map_reduce(self):
self.db.test.map_reduce('function() {}', 'function() {}', 'output',
Expand Down
13 changes: 0 additions & 13 deletions test/test_custom_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -588,19 +588,6 @@ def run_test(doc_cls):
for doc_cls in [RawBSONDocument, OrderedDict]:
run_test(doc_cls)

@client_context.require_version_max(4, 1, 0, -1)
def test_group_w_custom_type(self):
db = self.db
test = db.get_collection('test', codec_options=UNINT_CODECOPTS)
test.insert_many([
{'sku': 'a', 'qty': UndecipherableInt64Type(2)},
{'sku': 'b', 'qty': UndecipherableInt64Type(5)},
{'sku': 'a', 'qty': UndecipherableInt64Type(1)}])

self.assertEqual([{'sku': 'b', 'qty': UndecipherableInt64Type(5)},],
test.group(["sku", "qty"], {"sku": "b"}, {},
"function (obj, prev) { }"))

def test_aggregate_w_custom_type_decoder(self):
db = self.db
db.test.insert_many([
Expand Down
118 changes: 0 additions & 118 deletions test/test_legacy_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,124 +74,6 @@ def setUpClass(cls):
def tearDownClass(cls):
cls.deprecation_filter.stop()

@client_context.require_version_max(4, 1, 0, -1)
def test_group(self):
db = self.db
db.drop_collection("test")

self.assertEqual([],
db.test.group([], {}, {"count": 0},
"function (obj, prev) { prev.count++; }"
))

db.test.insert_many([{"a": 2}, {"b": 5}, {"a": 1}])

self.assertEqual([{"count": 3}],
db.test.group([], {}, {"count": 0},
"function (obj, prev) { prev.count++; }"
))

self.assertEqual([{"count": 1}],
db.test.group([], {"a": {"$gt": 1}}, {"count": 0},
"function (obj, prev) { prev.count++; }"
))

db.test.insert_one({"a": 2, "b": 3})

self.assertEqual([{"a": 2, "count": 2},
{"a": None, "count": 1},
{"a": 1, "count": 1}],
db.test.group(["a"], {}, {"count": 0},
"function (obj, prev) { prev.count++; }"
))

# modifying finalize
self.assertEqual([{"a": 2, "count": 3},
{"a": None, "count": 2},
{"a": 1, "count": 2}],
db.test.group(["a"], {}, {"count": 0},
"function (obj, prev) "
"{ prev.count++; }",
"function (obj) { obj.count++; }"))

# returning finalize
self.assertEqual([2, 1, 1],
db.test.group(["a"], {}, {"count": 0},
"function (obj, prev) "
"{ prev.count++; }",
"function (obj) { return obj.count; }"))

# keyf
self.assertEqual([2, 2],
db.test.group("function (obj) { if (obj.a == 2) "
"{ return {a: true} }; "
"return {b: true}; }", {}, {"count": 0},
"function (obj, prev) "
"{ prev.count++; }",
"function (obj) { return obj.count; }"))

# no key
self.assertEqual([{"count": 4}],
db.test.group(None, {}, {"count": 0},
"function (obj, prev) { prev.count++; }"
))

self.assertRaises(OperationFailure, db.test.group,
[], {}, {}, "5 ++ 5")

@client_context.require_version_max(4, 1, 0, -1)
def test_group_with_scope(self):
db = self.db
db.drop_collection("test")
db.test.insert_many([{"a": 1}, {"b": 1}])

reduce_function = "function (obj, prev) { prev.count += inc_value; }"

self.assertEqual(2, db.test.group([], {}, {"count": 0},
Code(reduce_function,
{"inc_value": 1}))[0]['count'])
self.assertEqual(4, db.test.group([], {}, {"count": 0},
Code(reduce_function,
{"inc_value": 2}))[0]['count'])

self.assertEqual(1,
db.test.group([], {}, {"count": 0},
Code(reduce_function,
{"inc_value": 0.5}))[0]['count'])

self.assertEqual(2, db.test.group(
[], {}, {"count": 0},
Code(reduce_function, {"inc_value": 1}))[0]['count'])

self.assertEqual(4, db.test.group(
[], {}, {"count": 0},
Code(reduce_function, {"inc_value": 2}))[0]['count'])

self.assertEqual(1, db.test.group(
[], {}, {"count": 0},
Code(reduce_function, {"inc_value": 0.5}))[0]['count'])

@client_context.require_version_max(4, 1, 0, -1)
def test_group_uuid_representation(self):
db = self.db
coll = db.uuid
coll.drop()
uu = uuid.uuid4()
coll.insert_one({"_id": uu, "a": 2})
coll.insert_one({"_id": uuid.uuid4(), "a": 1})

reduce = "function (obj, prev) { prev.count++; }"
coll = self.db.get_collection(
"uuid", CodecOptions(uuid_representation=STANDARD))
self.assertEqual([],
coll.group([], {"_id": uu},
{"count": 0}, reduce))
coll = self.db.get_collection(
"uuid", CodecOptions(uuid_representation=PYTHON_LEGACY))
self.assertEqual([{"count": 1}],
coll.group([], {"_id": uu},
{"count": 0}, reduce))


class TestLegacyBulk(BulkTestBase):

Expand Down
9 changes: 1 addition & 8 deletions test/test_read_preferences.py
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,7 @@ def setUpClass(cls):
if client_context.auth_enabled:
cls.c.admin.authenticate(db_user, db_pwd)
cls.client_version = Version.from_client(cls.c)
# mapReduce and group fail with no collection
# mapReduce fails if the collection does not exist.
coll = cls.c.pymongo_test.get_collection(
'test', write_concern=WriteConcern(w=client_context.w))
coll.insert_one({})
Expand Down Expand Up @@ -431,13 +431,6 @@ def test_create_collection(self):
lambda: self.c.pymongo_test.create_collection(
'some_collection%s' % random.randint(0, sys.maxsize)))

@client_context.require_version_max(4, 1, 0, -1)
def test_group(self):
with warnings.catch_warnings():
warnings.simplefilter("ignore")
self._test_coll_helper(True, self.c.pymongo_test.test, 'group',
{'a': 1}, {}, {}, 'function() { }')

def test_map_reduce(self):
self._test_coll_helper(False, self.c.pymongo_test.test, 'map_reduce',
'function() { }', 'function() { }',
Expand Down