summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKyle Suarez <kyle.suarez@mongodb.com>2017-11-22 10:43:58 -0500
committerKyle Suarez <kyle.suarez@mongodb.com>2017-11-29 11:02:58 -0500
commitfc8bff9cb031088e96cf8691b798e8d0a1be0207 (patch)
treeae532dee50a717e63c4be27f4924c4e0a4a44a8e
parent71b56638c7ece7be000da5b96d5f3c77ace85847 (diff)
downloadmongo-fc8bff9cb031088e96cf8691b798e8d0a1be0207.tar.gz
SERVER-30384 tests should specify a sort when expecting an ordering for a query
This refactors several tests in core to not rely on an implicit sort order, which allows them to be unblacklisted from the causally consistent jscore passthroughs. (cherry picked from commit 969ddd3d921cd8e6c5ab3068fdb77cb2dc271ed5)
-rw-r--r--buildscripts/resmokeconfig/suites/causally_consistent_jscore_passthrough.yml21
-rw-r--r--buildscripts/resmokeconfig/suites/causally_consistent_jscore_passthrough_auth.yml21
-rw-r--r--jstests/core/distinct1.js101
-rw-r--r--jstests/core/elemMatchProjection.js488
-rw-r--r--jstests/core/find4.js66
-rw-r--r--jstests/core/find5.js77
-rw-r--r--jstests/core/find_dedup.js69
-rw-r--r--jstests/core/fts1.js31
-rw-r--r--jstests/core/geo_distinct.js211
-rw-r--r--jstests/core/geo_s2ordering.js98
-rw-r--r--jstests/core/group1.js289
-rw-r--r--jstests/core/group2.js82
-rw-r--r--jstests/core/maxscan.js29
-rw-r--r--jstests/core/nan.js122
-rw-r--r--jstests/core/not2.js144
-rw-r--r--jstests/core/sort3.js24
-rw-r--r--jstests/core/sort4.js85
17 files changed, 959 insertions, 999 deletions
diff --git a/buildscripts/resmokeconfig/suites/causally_consistent_jscore_passthrough.yml b/buildscripts/resmokeconfig/suites/causally_consistent_jscore_passthrough.yml
index 21648575d6f..67faf503c33 100644
--- a/buildscripts/resmokeconfig/suites/causally_consistent_jscore_passthrough.yml
+++ b/buildscripts/resmokeconfig/suites/causally_consistent_jscore_passthrough.yml
@@ -111,32 +111,19 @@ selector:
- jstests/core/or4.js
- jstests/core/recursion.js
- jstests/core/temp_cleanup.js
+ # Tests that use $snapshot and expect documents to arrive in some implicit sort order are not
+ # causally consistent.
+ - jstests/core/snapshot_queries.js
+ - jstests/core/find1.js
# Tests that fail for Causal Consistency with default injected readPreference 'secondary'
# "TODO SERVER-30384: These tests assume that documents are returned in the same order they are
# written when no sort is specified; however, the order of documents within a collection can
# be different across a primary and secondary."
- jstests/core/coveredIndex1.js
- - jstests/core/distinct1.js
- - jstests/core/elemMatchProjection.js
- - jstests/core/find1.js
- - jstests/core/find4.js
- - jstests/core/find5.js
- - jstests/core/fts1.js
- - jstests/core/find_dedup.js
- jstests/core/fts_spanish.js
- - jstests/core/geo_distinct.js
- - jstests/core/geo_s2ordering.js
- - jstests/core/group1.js
- - jstests/core/group2.js
- - jstests/core/maxscan.js
- - jstests/core/nan.js
- jstests/core/null2.js
- - jstests/core/not2.js
- - jstests/core/snapshot_queries.js
- jstests/core/sorta.js
- jstests/core/sortc.js
- - jstests/core/sort3.js
- - jstests/core/sort4.js
- jstests/core/ord.js
# plan_cache tests does not work because they check the plan_cache on the primary while the
# cache is created on the secondary.
diff --git a/buildscripts/resmokeconfig/suites/causally_consistent_jscore_passthrough_auth.yml b/buildscripts/resmokeconfig/suites/causally_consistent_jscore_passthrough_auth.yml
index a3eaa46d3fd..9af91f857a9 100644
--- a/buildscripts/resmokeconfig/suites/causally_consistent_jscore_passthrough_auth.yml
+++ b/buildscripts/resmokeconfig/suites/causally_consistent_jscore_passthrough_auth.yml
@@ -126,32 +126,19 @@ selector:
- jstests/core/or4.js
- jstests/core/recursion.js
- jstests/core/temp_cleanup.js
+ # Tests that use $snapshot and expect documents to arrive in some implicit sort order are not
+ # causally consistent.
+ - jstests/core/snapshot_queries.js
+ - jstests/core/find1.js
# Tests that fail for Causal Consistency with default injected readPreference 'secondary'
# "TODO SERVER-30384: These tests assume that documents are returned in the same order they are
# written when no sort is specified; however, the order of documents within a collection can
# be different across a primary and secondary."
- jstests/core/coveredIndex1.js
- - jstests/core/distinct1.js
- - jstests/core/elemMatchProjection.js
- - jstests/core/find1.js
- - jstests/core/find4.js
- - jstests/core/find5.js
- - jstests/core/fts1.js
- - jstests/core/find_dedup.js
- jstests/core/fts_spanish.js
- - jstests/core/geo_distinct.js
- - jstests/core/geo_s2ordering.js
- - jstests/core/group1.js
- - jstests/core/group2.js
- - jstests/core/maxscan.js
- - jstests/core/nan.js
- jstests/core/null2.js
- - jstests/core/not2.js
- - jstests/core/snapshot_queries.js
- jstests/core/sorta.js
- jstests/core/sortc.js
- - jstests/core/sort3.js
- - jstests/core/sort4.js
- jstests/core/ord.js
# plan_cache tests does not work because they check the plan_cache on the primary while the
# cache is created on the secondary.
diff --git a/jstests/core/distinct1.js b/jstests/core/distinct1.js
index a70d027e51b..aee7b604926 100644
--- a/jstests/core/distinct1.js
+++ b/jstests/core/distinct1.js
@@ -1,62 +1,69 @@
+(function() {
+ "use strict";
+ const collName = "distinct1";
+ const coll = db.getCollection(collName);
+ coll.drop();
-t = db.distinct1;
-t.drop();
+ assert.eq(0, coll.distinct("a").length, "test empty");
-assert.eq(0, t.distinct("a").length, "test empty");
+ assert.writeOK(coll.insert({a: 1}));
+ assert.writeOK(coll.insert({a: 2}));
+ assert.writeOK(coll.insert({a: 2}));
+ assert.writeOK(coll.insert({a: 2}));
+ assert.writeOK(coll.insert({a: 3}));
-t.save({a: 1});
-t.save({a: 2});
-t.save({a: 2});
-t.save({a: 2});
-t.save({a: 3});
+ // Test that distinct returns all the distinct values.
+ assert.eq([1, 2, 3], coll.distinct("a").sort(), "distinct returned unexpected results");
-res = t.distinct("a");
-assert.eq("1,2,3", res.toString(), "A1");
+ // Test that distinct respects the query condition.
+ assert.eq([1, 2],
+ coll.distinct("a", {a: {$lt: 3}}).sort(),
+ "distinct with query returned unexpected results");
-assert.eq("1,2", t.distinct("a", {a: {$lt: 3}}), "A2");
+ assert(coll.drop());
-t.drop();
+ assert.writeOK(coll.insert({a: {b: "a"}, c: 12}));
+ assert.writeOK(coll.insert({a: {b: "b"}, c: 12}));
+ assert.writeOK(coll.insert({a: {b: "c"}, c: 12}));
+ assert.writeOK(coll.insert({a: {b: "c"}, c: 12}));
-t.save({a: {b: "a"}, c: 12});
-t.save({a: {b: "b"}, c: 12});
-t.save({a: {b: "c"}, c: 12});
-t.save({a: {b: "c"}, c: 12});
+ // Test that distinct works on fields in embedded documents.
+ assert.eq(["a", "b", "c"],
+ coll.distinct("a.b").sort(),
+ "distinct on dotted field returned unexpected results");
-res = t.distinct("a.b");
-assert.eq("a,b,c", res.toString(), "B1");
+ assert(coll.drop());
-t.drop();
+ assert.writeOK(coll.insert({_id: 1, a: 1}));
+ assert.writeOK(coll.insert({_id: 2, a: 2}));
-t.save({_id: 1, a: 1});
-t.save({_id: 2, a: 2});
+ // Test that distinct works on the _id field.
+ assert.eq([1, 2], coll.distinct("_id").sort(), "distinct on _id returned unexpected results");
-// Test distinct with _id.
-res = t.distinct("_id");
-assert.eq("1,2", res.toString(), "C1");
-res = t.distinct("a", {_id: 1});
-assert.eq("1", res.toString(), "C2");
+ // Test that distinct works with a query on the _id field.
+ assert.eq([1],
+ coll.distinct("a", {_id: 1}),
+ "distinct with query on _id returned unexpected results");
-// Test distinct with db.runCommand
-t.drop();
+ assert(coll.drop());
-t.save({a: 1, b: 2});
-t.save({a: 2, b: 2});
-t.save({a: 2, b: 1});
-t.save({a: 2, b: 2});
-t.save({a: 3, b: 2});
-t.save({a: 4, b: 1});
-t.save({a: 4, b: 1});
+ assert.writeOK(coll.insert({a: 1, b: 2}));
+ assert.writeOK(coll.insert({a: 2, b: 2}));
+ assert.writeOK(coll.insert({a: 2, b: 1}));
+ assert.writeOK(coll.insert({a: 2, b: 2}));
+ assert.writeOK(coll.insert({a: 3, b: 2}));
+ assert.writeOK(coll.insert({a: 4, b: 1}));
+ assert.writeOK(coll.insert({a: 4, b: 1}));
-res = db.runCommand({distinct: "distinct1", key: "a"});
-assert.commandWorked(res);
-assert.eq([1, 2, 3, 4], res["values"], "D1");
-res = db.runCommand({distinct: "distinct1", key: "a", query: null});
-assert.commandWorked(res);
-assert.eq([1, 2, 3, 4], res["values"], "D2");
-res = db.runCommand({distinct: "distinct1", key: "a", query: {b: 2}});
-assert.commandWorked(res);
-assert.eq([1, 2, 3], res["values"], "D3");
-res = db.runCommand({distinct: "distinct1", key: "a", query: 1});
-assert.commandFailed(res);
+ // Test running the distinct command directly, rather than via shell helper.
+ let res = assert.commandWorked(db.runCommand({distinct: collName, key: "a"}));
+ assert.eq([1, 2, 3, 4], res.values.sort());
-t.drop();
+ res = assert.commandWorked(db.runCommand({distinct: collName, key: "a", query: null}));
+ assert.eq([1, 2, 3, 4], res.values.sort());
+
+ res = assert.commandWorked(db.runCommand({distinct: collName, key: "a", query: {b: 2}}));
+ assert.eq([1, 2, 3], res.values.sort());
+
+ assert.commandFailed(db.runCommand({distinct: collName, key: "a", query: 1}));
+}());
diff --git a/jstests/core/elemMatchProjection.js b/jstests/core/elemMatchProjection.js
index ce4fd0639a7..7114959b6ca 100644
--- a/jstests/core/elemMatchProjection.js
+++ b/jstests/core/elemMatchProjection.js
@@ -1,273 +1,221 @@
// Tests for $elemMatch projections and $ positional operator projection.
-t = db.SERVER828Test;
-t.drop();
-
-date1 = new Date();
-
-// Insert various styles of arrays
-for (i = 0; i < 100; i++) {
- t.insert({group: 1, x: [1, 2, 3, 4, 5]});
- t.insert({group: 2, x: [{a: 1, b: 2}, {a: 2, c: 3}, {a: 1, d: 5}]});
- t.insert({
- group: 3,
- x: [{a: 1, b: 2}, {a: 2, c: 3}, {a: 1, d: 5}],
- y: [{aa: 1, bb: 2}, {aa: 2, cc: 3}, {aa: 1, dd: 5}]
- });
- t.insert({group: 3, x: [{a: 1, b: 3}, {a: -6, c: 3}]});
- t.insert({group: 4, x: [{a: 1, b: 4}, {a: -6, c: 3}]});
- t.insert({group: 5, x: [new Date(), 5, 10, 'string', new ObjectId(), 123.456]});
- t.insert({
- group: 6,
- x: [{a: 'string', b: date1}, {a: new ObjectId(), b: 1.2345}, {a: 'string2', b: date1}]
- });
- t.insert({group: 7, x: [{y: [1, 2, 3, 4]}]});
- t.insert({group: 8, x: [{y: [{a: 1, b: 2}, {a: 3, b: 4}]}]});
- t.insert({group: 9, x: [{y: [{a: 1, b: 2}, {a: 3, b: 4}]}, {z: [{a: 1, b: 2}, {a: 3, b: 4}]}]});
- t.insert({group: 10, x: [{a: 1, b: 2}, {a: 3, b: 4}], y: [{c: 1, d: 2}, {c: 3, d: 4}]});
- t.insert({group: 10, x: [{a: 1, b: 2}, {a: 3, b: 4}], y: [{c: 1, d: 2}, {c: 3, d: 4}]});
- t.insert({
- group: 11,
- x: [{a: 1, b: 2}, {a: 2, c: 3}, {a: 1, d: 5}],
- covered: [{aa: 1, bb: 2}, {aa: 2, cc: 3}, {aa: 1, dd: 5}]
- });
- t.insert({group: 12, x: {y: [{a: 1, b: 1}, {a: 1, b: 2}]}});
- t.insert({group: 13, x: [{a: 1, b: 1}, {a: 1, b: 2}]});
- t.insert({group: 13, x: [{a: 1, b: 2}, {a: 1, b: 1}]});
-}
-t.ensureIndex({
- group: 1,
- 'y.d': 1
-}); // for regular index test (not sure if this is really adding anything useful)
-t.ensureIndex({group: 1, covered: 1}); // for covered index test
-
-//
-// SERVER-828: Positional operator ($) projection tests
-//
-assert.eq(1,
- t.find({group: 3, 'x.a': 2}, {'x.$': 1}).toArray()[0].x.length,
- "single object match (array length match)");
-
-assert.eq(
- 2, t.find({group: 3, 'x.a': 1}, {'x.$': 1}).toArray()[0].x[0].b, "single object match first");
-
-assert.eq(undefined,
- t.find({group: 3, 'x.a': 2}, {_id: 0, 'x.$': 1}).toArray()[0]._id,
- "single object match with filtered _id");
-
-assert.eq(1,
- t.find({group: 3, 'x.a': 2}, {'x.$': 1}).sort({_id: 1}).toArray()[0].x.length,
- "sorted single object match with filtered _id (array length match)");
-
-assert.eq(
- 1,
- t.find({'group': 2, 'x': {'$elemMatch': {'a': 1, 'b': 2}}}, {'x.$': 1}).toArray()[0].x.length,
- "single object match with elemMatch");
-
-assert.eq(1,
- t.find({'group': 2, 'x': {'$elemMatch': {'a': 1, 'b': 2}}}, {'x.$': {'$slice': 1}})
- .toArray()[0]
- .x.length,
- "single object match with elemMatch and positive slice");
-
-assert.eq(1,
- t.find({'group': 2, 'x': {'$elemMatch': {'a': 1, 'b': 2}}}, {'x.$': {'$slice': -1}})
- .toArray()[0]
- .x.length,
- "single object match with elemMatch and negative slice");
-
-assert.eq(1,
- t.find({'group': 12, 'x.y.a': 1}, {'x.y.$': 1}).toArray()[0].x.y.length,
- "single object match with two level dot notation");
-
-assert.eq(1,
- t.find({group: 3, 'x.a': 2}, {'x.$': 1}).sort({x: 1}).toArray()[0].x.length,
- "sorted object match (array length match)");
-
-assert.eq({aa: 1, dd: 5},
- t.find({group: 3, 'y.dd': 5}, {'y.$': 1}).toArray()[0].y[0],
- "single object match (value match)");
-
-assert.throws(function() {
- t.find({group: 3, 'x.a': 2}, {'y.$': 1}).toArray();
-}, [], "throw on invalid projection (field mismatch)");
-
-assert.throws(function() {
- t.find({group: 3, 'x.a': 2}, {'y.$': 1}).sort({x: 1}).toArray();
-}, [], "throw on invalid sorted projection (field mismatch)");
-
-assert.throws(function() {
- t.find({group: 3, 'x.a': 2}, {'x.$': 1, group: 0}).sort({x: 1}).toArray();
-}, [], "throw on invalid projection combination (include and exclude)");
-
-assert.throws(function() {
- t.find({group: 3, 'x.a': 1, 'y.aa': 1}, {'x.$': 1, 'y.$': 1}).toArray();
-}, [], "throw on multiple projections");
-
-assert.throws(function() {
- t.find({group: 3}, {'g.$': 1}).toArray();
-}, [], "throw on invalid projection (non-array field)");
-
-assert.eq({aa: 1, dd: 5},
- t.find({group: 11, 'covered.dd': 5}, {'covered.$': 1}).toArray()[0].covered[0],
- "single object match (covered index)");
-
-assert.eq({aa: 1, dd: 5},
- t.find({group: 11, 'covered.dd': 5}, {'covered.$': 1})
- .sort({covered: 1})
- .toArray()[0]
- .covered[0],
- "single object match (sorted covered index)");
-
-assert.eq(1,
- t.find({group: 10, 'y.d': 4}, {'y.$': 1}).toArray()[0].y.length,
- "single object match (regular index");
-
-if (false) {
- assert.eq(2, // SERVER-1013: allow multiple positional operators
- t.find({group: 3, 'y.bb': 2, 'x.d': 5}, {'y.$': 1, 'x.$': 1}).toArray()[0].y[0].bb,
- "multi match, multi proj 1");
-
- assert.eq(5, // SSERVER-1013: allow multiple positional operators
- t.find({group: 3, 'y.bb': 2, 'x.d': 5}, {'y.$': 1, 'x.$': 1}).toArray()[0].x[0].d,
- "multi match, multi proj 2");
-
- assert.eq(2, // SERVER-1243: allow multiple results from same matcher
- t.find({group: 2, x: {$elemMatchAll: {a: 1}}}, {'x.$': 1}).toArray()[0].x.length,
- "multi element match, single proj");
-
- assert.eq(2, // SERVER-1013: multiple array matches with one prositional operator
- t.find({group: 3, 'y.bb': 2, 'x.d': 5}, {'y.$': 1}).toArray()[0].y[0].bb,
- "multi match, single proj 1");
-
- assert.eq(2, // SERVER-1013: multiple array matches with one positional operator
- t.find({group: 3, 'y.cc': 3, 'x.b': 2}, {'x.$': 1}).toArray()[0].x[0].b,
- "multi match, single proj 2");
-}
-
-//
-// SERVER-2238: $elemMatch projections
-//
-assert.eq(
- -6, t.find({group: 4}, {x: {$elemMatch: {a: -6}}}).toArray()[0].x[0].a, "single object match");
-
-assert.eq(1,
- t.find({group: 4}, {x: {$elemMatch: {a: -6}}}).toArray()[0].x.length,
- "filters non-matching array elements");
-
-assert.eq(1,
- t.find({group: 4}, {x: {$elemMatch: {a: -6, c: 3}}}).toArray()[0].x.length,
- "filters non-matching array elements with multiple elemMatch criteria");
-
-assert.eq(
- 1,
- t.find({group: 13}, {'x': {'$elemMatch': {a: {$gt: 0, $lt: 2}}}}).toArray()[0].x.length,
- "filters non-matching array elements with multiple criteria for a single element in the array");
-
-assert.eq(3,
- t.find({group: 4}, {x: {$elemMatch: {a: {$lt: 1}}}}).toArray()[0].x[0].c,
- "object operator match");
-
-assert.eq([4],
- t.find({group: 1}, {x: {$elemMatch: {$in: [100, 4, -123]}}}).toArray()[0].x,
- "$in number match");
-
-assert.eq([{a: 1, b: 2}],
- t.find({group: 2}, {x: {$elemMatch: {a: {$in: [1]}}}}).toArray()[0].x,
- "$in number match");
-
-assert.eq([1],
- t.find({group: 1}, {x: {$elemMatch: {$nin: [4, 5, 6]}}}).toArray()[0].x,
- "$nin number match");
-
-// but this may become a user assertion, since a single element of an array can't match more than
-// one value
-assert.eq(
- [1], t.find({group: 1}, {x: {$elemMatch: {$all: [1]}}}).toArray()[0].x, "$in number match");
-
-assert.eq([{a: 'string', b: date1}],
- t.find({group: 6}, {x: {$elemMatch: {a: 'string'}}}).toArray()[0].x,
- "mixed object match on string eq");
-
-assert.eq([{a: 'string2', b: date1}],
- t.find({group: 6}, {x: {$elemMatch: {a: /ring2/}}}).toArray()[0].x,
- "mixed object match on regexp");
-
-assert.eq([{a: 'string', b: date1}],
- t.find({group: 6}, {x: {$elemMatch: {a: {$type: 2}}}}).toArray()[0].x,
- "mixed object match on type");
-
-assert.eq([{a: 2, c: 3}],
- t.find({group: 2}, {x: {$elemMatch: {a: {$ne: 1}}}}).toArray()[0].x,
- "mixed object match on ne");
-
-assert.eq([{a: 1, d: 5}],
- t.find({group: 3}, {x: {$elemMatch: {d: {$exists: true}}}}).toArray()[0].x,
- "mixed object match on exists");
-
-assert.eq([{a: 2, c: 3}],
- t.find({group: 3}, {x: {$elemMatch: {a: {$mod: [2, 0]}}}}).toArray()[0].x,
- "mixed object match on mod");
-
-assert.eq(
- {"x": [{"a": 1, "b": 2}], "y": [{"c": 3, "d": 4}]},
- t.find({group: 10}, {_id: 0, x: {$elemMatch: {a: 1}}, y: {$elemMatch: {c: 3}}}).toArray()[0],
- "multiple $elemMatch on unique fields 1");
-
-if (false) {
- assert.eq(2, // SERVER-1243: handle multiple $elemMatch results
- t.find({group: 4}, {x: {$elemMatchAll: {a: {$lte: 2}}}}).toArray()[0].x.length,
- "multi object match");
-
- assert.eq(3, // SERVER-1243: handle multiple $elemMatch results
- t.find({group: 1}, {x: {$elemMatchAll: {$in: [1, 2, 3]}}}).toArray()[0].x.length,
+(function() {
+ "use strict";
+
+ const coll = db.SERVER828Test;
+ coll.drop();
+
+ const date1 = new Date();
+
+ // Insert various styles of arrays.
+ const bulk = coll.initializeUnorderedBulkOp();
+ for (let i = 0; i < 100; i++) {
+ bulk.insert({group: 1, x: [1, 2, 3, 4, 5]});
+ bulk.insert({group: 2, x: [{a: 1, b: 2}, {a: 2, c: 3}, {a: 1, d: 5}]});
+ bulk.insert({
+ group: 3,
+ x: [{a: 1, b: 2}, {a: 2, c: 3}, {a: 1, d: 5}],
+ y: [{aa: 1, bb: 2}, {aa: 2, cc: 3}, {aa: 1, dd: 5}]
+ });
+ bulk.insert({group: 3, x: [{a: 1, b: 3}, {a: -6, c: 3}]});
+ bulk.insert({group: 4, x: [{a: 1, b: 4}, {a: -6, c: 3}]});
+ bulk.insert({group: 5, x: [new Date(), 5, 10, 'string', new ObjectId(), 123.456]});
+ bulk.insert({
+ group: 6,
+ x: [
+ {a: 'string', b: date1},
+ {a: new ObjectId(), b: 1.2345},
+ {a: 'string2', b: date1}
+ ]
+ });
+ bulk.insert({group: 7, x: [{y: [1, 2, 3, 4]}]});
+ bulk.insert({group: 8, x: [{y: [{a: 1, b: 2}, {a: 3, b: 4}]}]});
+ bulk.insert(
+ {group: 9, x: [{y: [{a: 1, b: 2}, {a: 3, b: 4}]}, {z: [{a: 1, b: 2}, {a: 3, b: 4}]}]});
+ bulk.insert({group: 10, x: [{a: 1, b: 2}, {a: 3, b: 4}], y: [{c: 1, d: 2}, {c: 3, d: 4}]});
+ bulk.insert({group: 10, x: [{a: 1, b: 2}, {a: 3, b: 4}], y: [{c: 1, d: 2}, {c: 3, d: 4}]});
+ bulk.insert({
+ group: 11,
+ x: [{a: 1, b: 2}, {a: 2, c: 3}, {a: 1, d: 5}],
+ covered: [{aa: 1, bb: 2}, {aa: 2, cc: 3}, {aa: 1, dd: 5}]
+ });
+ bulk.insert({group: 12, x: {y: [{a: 1, b: 1}, {a: 1, b: 2}]}});
+ bulk.insert({group: 13, x: [{a: 1, b: 1}, {a: 1, b: 2}]});
+ bulk.insert({group: 13, x: [{a: 1, b: 2}, {a: 1, b: 1}]});
+ }
+ assert.writeOK(bulk.execute());
+
+ assert.writeOK(coll.createIndex({group: 1, 'y.d': 1}));
+ assert.writeOK(coll.createIndex({group: 1, covered: 1})); // for covered index test
+
+ // Tests for the $-positional operator.
+ assert.eq(1,
+ coll.find({group: 3, 'x.a': 2}, {'x.$': 1}).sort({_id: 1}).toArray()[0].x.length,
+ "single object match (array length match)");
+
+ assert.eq(2,
+ coll.find({group: 3, 'x.a': 1}, {'x.$': 1}).sort({_id: 1}).toArray()[0].x[0].b,
+ "single object match first");
+
+ assert.eq(undefined,
+ coll.find({group: 3, 'x.a': 2}, {_id: 0, 'x.$': 1}).sort({_id: 1}).toArray()[0]._id,
+ "single object match with filtered _id");
+
+ assert.eq(1,
+ coll.find({group: 3, 'x.a': 2}, {'x.$': 1}).sort({_id: 1}).toArray()[0].x.length,
+ "sorted single object match with filtered _id (array length match)");
+
+ assert.eq(1,
+ coll.find({'group': 2, 'x': {'$elemMatch': {'a': 1, 'b': 2}}}, {'x.$': 1})
+ .toArray()[0]
+ .x.length,
+ "single object match with elemMatch");
+
+ assert.eq(1,
+ coll.find({'group': 2, 'x': {'$elemMatch': {'a': 1, 'b': 2}}}, {'x.$': {'$slice': 1}})
+ .toArray()[0]
+ .x.length,
+ "single object match with elemMatch and positive slice");
+
+ assert.eq(
+ 1,
+ coll.find({'group': 2, 'x': {'$elemMatch': {'a': 1, 'b': 2}}}, {'x.$': {'$slice': -1}})
+ .toArray()[0]
+ .x.length,
+ "single object match with elemMatch and negative slice");
+
+ assert.eq(1,
+ coll.find({'group': 12, 'x.y.a': 1}, {'x.y.$': 1}).toArray()[0].x.y.length,
+ "single object match with two level dot notation");
+
+ assert.eq(1,
+ coll.find({group: 3, 'x.a': 2}, {'x.$': 1}).sort({x: 1}).toArray()[0].x.length,
+ "sorted object match (array length match)");
+
+ assert.eq({aa: 1, dd: 5},
+ coll.find({group: 3, 'y.dd': 5}, {'y.$': 1}).sort({_id: 1}).toArray()[0].y[0],
+ "single object match (value match)");
+
+ assert.throws(function() {
+ coll.find({group: 3, 'x.a': 2}, {'y.$': 1}).toArray();
+ }, [], "throw on invalid projection (field mismatch)");
+
+ assert.throws(function() {
+ coll.find({group: 3, 'x.a': 2}, {'y.$': 1}).sort({x: 1}).toArray();
+ }, [], "throw on invalid sorted projection (field mismatch)");
+
+ assert.throws(function() {
+ coll.find({group: 3, 'x.a': 2}, {'x.$': 1, group: 0}).sort({x: 1}).toArray();
+ }, [], "throw on invalid projection combination (include and exclude)");
+
+ assert.throws(function() {
+ coll.find({group: 3, 'x.a': 1, 'y.aa': 1}, {'x.$': 1, 'y.$': 1}).toArray();
+ }, [], "throw on multiple projections");
+
+ assert.throws(function() {
+ coll.find({group: 3}, {'g.$': 1}).toArray();
+ }, [], "throw on invalid projection (non-array field)");
+
+ assert.eq({aa: 1, dd: 5},
+ coll.find({group: 11, 'covered.dd': 5}, {'covered.$': 1}).toArray()[0].covered[0],
+ "single object match (covered index)");
+
+ assert.eq({aa: 1, dd: 5},
+ coll.find({group: 11, 'covered.dd': 5}, {'covered.$': 1})
+ .sort({covered: 1})
+ .toArray()[0]
+ .covered[0],
+ "single object match (sorted covered index)");
+
+ assert.eq(1,
+ coll.find({group: 10, 'y.d': 4}, {'y.$': 1}).sort({_id: 1}).toArray()[0].y.length,
+ "single object match (regular index");
+
+ // Tests for $elemMatch projection.
+ assert.eq(-6,
+ coll.find({group: 4}, {x: {$elemMatch: {a: -6}}}).toArray()[0].x[0].a,
+ "single object match");
+
+ assert.eq(1,
+ coll.find({group: 4}, {x: {$elemMatch: {a: -6}}}).toArray()[0].x.length,
+ "filters non-matching array elements");
+
+ assert.eq(1,
+ coll.find({group: 4}, {x: {$elemMatch: {a: -6, c: 3}}}).toArray()[0].x.length,
+ "filters non-matching array elements with multiple elemMatch criteria");
+
+ assert.eq(
+ 1,
+ coll.find({group: 13}, {'x': {'$elemMatch': {a: {$gt: 0, $lt: 2}}}})
+ .sort({_id: 1})
+ .toArray()[0]
+ .x.length,
+ "filters non-matching array elements with multiple criteria for a single element in the array");
+
+ assert.eq(
+ 3,
+ coll.find({group: 4}, {x: {$elemMatch: {a: {$lt: 1}}}}).sort({_id: 1}).toArray()[0].x[0].c,
+ "object operator match");
+
+ assert.eq([4],
+ coll.find({group: 1}, {x: {$elemMatch: {$in: [100, 4, -123]}}}).toArray()[0].x,
"$in number match");
- assert.eq(1, // SERVER-1243: handle multiple $elemMatch results
- t.find({group: 5}, {x: {$elemMatchAll: {$ne: 5}}}).toArray()[0].x.length,
- "single mixed type match 1");
-
- assert.eq(1, // SERVER-831: handle nested arrays
- t.find({group: 9}, {'x.y': {$elemMatch: {a: 1}}}).toArray()[0].x.length,
- "single dotted match");
-}
-
-//
-// Batch/getMore tests
-//
-// test positional operator across multiple batches
-a = t.find({group: 3, 'x.b': 2}, {'x.$': 1}).batchSize(1);
-while (a.hasNext()) {
- assert.eq(2, a.next().x[0].b, "positional getMore test");
-}
-
-// test $elemMatch operator across multiple batches
-a = t.find({group: 3}, {x: {$elemMatch: {a: 1}}}).batchSize(1);
-while (a.hasNext()) {
- assert.eq(1, a.next().x[0].a, "positional getMore test");
-}
-
-// verify the positional update operator matches the same element as the the positional find. this
-// is to ensure consistent behavior with updates until SERVER-1013 is resolved, at which point the
-// following tests should be updated.
-
-t.update({group: 10, 'x.a': 3, 'y.c': 1}, {$set: {'x.$': 100}}, false, true);
-// updated the wrong element, so the following assertions should be true
-assert.eq(100,
- t.find({group: 10, 'y.c': 1, x: 100}, {'x.$': 1}).toArray()[0].x[0],
- "wrong single element match after update");
-
-assert.eq(100,
- t.find({group: 10, x: 100, 'y.c': 1}, {'x.$': 1}).toArray()[0].x[0],
- "wrong single element match after update");
-
-t.remove({group: 10});
-t.insert({group: 10, x: [{a: 1, b: 2}, {a: 3, b: 4}], y: [{c: 1, d: 2}, {c: 3, d: 4}]});
-
-t.update({group: 10, 'y.c': 1, 'x.a': 3}, {$set: {'x.$': 100}}, false, true);
-// updated the correct element
-assert.eq(100,
- t.find({group: 10, 'y.c': 1, x: 100}, {'x.$': 1}).toArray()[0].x[0],
- "right single element match after update");
-assert.eq(100,
- t.find({group: 10, x: 100, 'y.c': 1}, {'x.$': 1}).toArray()[0].x[0],
- "right single element match after update");
+ assert.eq([{a: 1, b: 2}],
+ coll.find({group: 2}, {x: {$elemMatch: {a: {$in: [1]}}}}).toArray()[0].x,
+ "$in number match");
+
+ assert.eq([1],
+ coll.find({group: 1}, {x: {$elemMatch: {$nin: [4, 5, 6]}}}).toArray()[0].x,
+ "$nin number match");
+
+ assert.eq([1],
+ coll.find({group: 1}, {x: {$elemMatch: {$all: [1]}}}).toArray()[0].x,
+ "$in number match");
+
+ assert.eq([{a: 'string', b: date1}],
+ coll.find({group: 6}, {x: {$elemMatch: {a: 'string'}}}).toArray()[0].x,
+ "mixed object match on string eq");
+
+ assert.eq([{a: 'string2', b: date1}],
+ coll.find({group: 6}, {x: {$elemMatch: {a: /ring2/}}}).toArray()[0].x,
+ "mixed object match on regexp");
+
+ assert.eq([{a: 'string', b: date1}],
+ coll.find({group: 6}, {x: {$elemMatch: {a: {$type: 2}}}}).toArray()[0].x,
+ "mixed object match on type");
+
+ assert.eq([{a: 2, c: 3}],
+ coll.find({group: 2}, {x: {$elemMatch: {a: {$ne: 1}}}}).toArray()[0].x,
+ "mixed object match on ne");
+
+ assert.eq([{a: 1, d: 5}],
+ coll.find({group: 3}, {x: {$elemMatch: {d: {$exists: true}}}})
+ .sort({_id: 1})
+ .toArray()[0]
+ .x,
+ "mixed object match on exists");
+
+ assert.eq(
+ [{a: 2, c: 3}],
+ coll.find({group: 3}, {x: {$elemMatch: {a: {$mod: [2, 0]}}}}).sort({_id: 1}).toArray()[0].x,
+ "mixed object match on mod");
+
+ assert.eq({"x": [{"a": 1, "b": 2}], "y": [{"c": 3, "d": 4}]},
+ coll.find({group: 10}, {_id: 0, x: {$elemMatch: {a: 1}}, y: {$elemMatch: {c: 3}}})
+ .sort({_id: 1})
+ .toArray()[0],
+ "multiple $elemMatch on unique fields 1");
+
+ // Tests involving getMore. Test the $-positional operator across multiple batches.
+ let a = coll.find({group: 3, 'x.b': 2}, {'x.$': 1}).sort({_id: 1}).batchSize(1);
+ while (a.hasNext()) {
+ assert.eq(2, a.next().x[0].b, "positional getMore test");
+ }
+
+ // Test the $elemMatch operator across multiple batches.
+ a = coll.find({group: 3}, {x: {$elemMatch: {a: 1}}}).sort({_id: 1}).batchSize(1);
+ while (a.hasNext()) {
+ assert.eq(1, a.next().x[0].a, "positional getMore test");
+ }
+}());
diff --git a/jstests/core/find4.js b/jstests/core/find4.js
index 204e7c511e2..ad482916a19 100644
--- a/jstests/core/find4.js
+++ b/jstests/core/find4.js
@@ -1,36 +1,42 @@
+(function() {
+ "use strict";
-t = db.find4;
-t.drop();
+ const coll = db.find4;
+ coll.drop();
-t.save({a: 1123, b: 54332});
+ assert.writeOK(coll.insert({a: 1123, b: 54332}));
-o = t.find({}, {})[0];
-assert.eq(1123, o.a, "A");
-assert.eq(54332, o.b, "B");
-assert(o._id.str, "C");
+ let o = coll.findOne();
+ assert.eq(1123, o.a, "A");
+ assert.eq(54332, o.b, "B");
+ assert(o._id.str, "C");
-o = t.find({}, {a: 1})[0];
-assert.eq(1123, o.a, "D");
-assert(o._id.str, "E");
-assert(!o.b, "F");
+ o = coll.findOne({}, {a: 1});
+ assert.eq(1123, o.a, "D");
+ assert(o._id.str, "E");
+ assert(!o.b, "F");
-o = t.find({}, {b: 1})[0];
-assert.eq(54332, o.b, "G");
-assert(o._id.str, "H");
-assert(!o.a, "I");
+ o = coll.findOne({}, {b: 1});
+ assert.eq(54332, o.b, "G");
+ assert(o._id.str, "H");
+ assert(!o.a, "I");
-t.drop();
-t.save({a: 1, b: 1});
-t.save({a: 2, b: 2});
-assert.eq("1-1,2-2",
- t.find()
- .map(function(z) {
- return z.a + "-" + z.b;
- })
- .toString());
-assert.eq("1-undefined,2-undefined",
- t.find({}, {a: 1})
- .map(function(z) {
- return z.a + "-" + z.b;
- })
- .toString());
+ assert(coll.drop());
+
+ assert.writeOK(coll.insert({a: 1, b: 1}));
+ assert.writeOK(coll.insert({a: 2, b: 2}));
+ assert.eq("1-1,2-2",
+ coll.find()
+ .sort({a: 1})
+ .map(function(z) {
+ return z.a + "-" + z.b;
+ })
+ .toString());
+ assert.eq("1-undefined,2-undefined",
+ coll.find({}, {a: 1})
+ .sort({a: 1})
+ .map(function(z) {
+ return z.a + "-" + z.b;
+ })
+ .toString());
+}());
diff --git a/jstests/core/find5.js b/jstests/core/find5.js
index 33ba96ea103..633b723fe5a 100644
--- a/jstests/core/find5.js
+++ b/jstests/core/find5.js
@@ -1,51 +1,54 @@
+(function() {
+ "use strict";
-t = db.find5;
-t.drop();
+ const coll = db.find5;
+ coll.drop();
-t.save({a: 1});
-t.save({b: 5});
+ assert.writeOK(coll.insert({a: 1}));
+ assert.writeOK(coll.insert({b: 5}));
-assert.eq(2, t.find({}, {b: 1}).count(), "A");
+ assert.eq(2, coll.find({}, {b: 1}).count(), "A");
-function getIds(f) {
- return t.find({}, f).map(function(z) {
- return z._id;
- });
-}
+ function getIds(projection) {
+ return coll.find({}, projection).map(doc => doc._id);
+ }
-assert.eq(Array.tojson(getIds(null)), Array.tojson(getIds({})), "B1 ");
-assert.eq(Array.tojson(getIds(null)), Array.tojson(getIds({a: 1})), "B2 ");
-assert.eq(Array.tojson(getIds(null)), Array.tojson(getIds({b: 1})), "B3 ");
-assert.eq(Array.tojson(getIds(null)), Array.tojson(getIds({c: 1})), "B4 ");
+ assert.eq(Array.tojson(getIds(null)), Array.tojson(getIds({})), "B1 ");
+ assert.eq(Array.tojson(getIds(null)), Array.tojson(getIds({a: 1})), "B2 ");
+ assert.eq(Array.tojson(getIds(null)), Array.tojson(getIds({b: 1})), "B3 ");
+ assert.eq(Array.tojson(getIds(null)), Array.tojson(getIds({c: 1})), "B4 ");
-x = t.find({}, {a: 1})[0];
-assert.eq(1, x.a, "C1");
-assert.isnull(x.b, "C2");
+ let results = coll.find({}, {a: 1}).sort({a: -1});
+ let first = results[0];
+ assert.eq(1, first.a, "C1");
+ assert.isnull(first.b, "C2");
-x = t.find({}, {a: 1})[1];
-assert.isnull(x.a, "C3");
-assert.isnull(x.b, "C4");
+ let second = results[1];
+ assert.isnull(second.a, "C3");
+ assert.isnull(second.b, "C4");
-x = t.find({}, {b: 1})[0];
-assert.isnull(x.a, "C5");
-assert.isnull(x.b, "C6");
+ results = coll.find({}, {b: 1}).sort({a: -1});
+ first = results[0];
+ assert.isnull(first.a, "C5");
+ assert.isnull(first.b, "C6");
-x = t.find({}, {b: 1})[1];
-assert.isnull(x.a, "C7");
-assert.eq(5, x.b, "C8");
+ second = results[1];
+ assert.isnull(second.a, "C7");
+ assert.eq(5, second.b, "C8");
-t.drop();
+ assert(coll.drop());
-t.save({a: 1, b: {c: 2, d: 3, e: 4}});
-assert.eq(2, t.find({}, {"b.c": 1}).toArray()[0].b.c, "D");
+ assert.writeOK(coll.insert({a: 1, b: {c: 2, d: 3, e: 4}}));
+ assert.eq(2, coll.findOne({}, {"b.c": 1}).b.c, "D");
-o = t.find({}, {"b.c": 1, "b.d": 1}).toArray()[0];
-assert(o.b.c, "E 1");
-assert(o.b.d, "E 2");
-assert(!o.b.e, "E 3");
+ const o = coll.findOne({}, {"b.c": 1, "b.d": 1});
+ assert(o.b.c, "E 1");
+ assert(o.b.d, "E 2");
+ assert(!o.b.e, "E 3");
-assert(!t.find({}, {"b.c": 1}).toArray()[0].b.d, "F");
+ assert(!coll.findOne({}, {"b.c": 1}).b.d, "F");
-t.drop();
-t.save({a: {b: {c: 1}}});
-assert.eq(1, t.find({}, {"a.b.c": 1})[0].a.b.c, "G");
+ assert(coll.drop());
+ assert.writeOK(coll.insert({a: {b: {c: 1}}}));
+ assert.eq(1, coll.findOne({}, {"a.b.c": 1}).a.b.c, "G");
+}());
diff --git a/jstests/core/find_dedup.js b/jstests/core/find_dedup.js
index 7a489bd185c..7e9bef61160 100644
--- a/jstests/core/find_dedup.js
+++ b/jstests/core/find_dedup.js
@@ -1,39 +1,44 @@
// Test that duplicate query results are not returned.
+(function() {
+ "use strict";
-var t = db.jstests_find_dedup;
+ const coll = db.jstests_find_dedup;
-function checkDedup(query, idArray) {
- resultsArr = t.find(query).toArray();
- assert.eq(resultsArr.length, idArray.length, "same number of results");
+ function checkDedup(query, idArray) {
+ const resultsArr = coll.find(query).sort({_id: 1}).toArray();
+ assert.eq(resultsArr.length, idArray.length, "same number of results");
- for (var i = 0; i < idArray.length; i++) {
- assert(("_id" in resultsArr[i]), "result doc missing _id");
- assert.eq(idArray[i], resultsArr[i]._id, "_id mismatch for doc " + i);
+ for (let i = 0; i < idArray.length; i++) {
+ assert(("_id" in resultsArr[i]), "result doc missing _id");
+ assert.eq(idArray[i], resultsArr[i]._id, "_id mismatch for doc " + i);
+ }
}
-}
-// Deduping $or
-t.drop();
-t.ensureIndex({a: 1, b: 1});
-t.save({_id: 1, a: 1, b: 1});
-t.save({_id: 2, a: 1, b: 1});
-t.save({_id: 3, a: 2, b: 2});
-t.save({_id: 4, a: 3, b: 3});
-t.save({_id: 5, a: 3, b: 3});
-checkDedup({
- $or: [
- {a: {$gte: 0, $lte: 2}, b: {$gte: 0, $lte: 2}},
- {a: {$gte: 1, $lte: 3}, b: {$gte: 1, $lte: 3}},
- {a: {$gte: 1, $lte: 4}, b: {$gte: 1, $lte: 4}}
- ]
-},
- [1, 2, 3, 4, 5]);
+ // Deduping $or
+ coll.drop();
+ coll.ensureIndex({a: 1, b: 1});
+ assert.writeOK(coll.insert({_id: 1, a: 1, b: 1}));
+ assert.writeOK(coll.insert({_id: 2, a: 1, b: 1}));
+ assert.writeOK(coll.insert({_id: 3, a: 2, b: 2}));
+ assert.writeOK(coll.insert({_id: 4, a: 3, b: 3}));
+ assert.writeOK(coll.insert({_id: 5, a: 3, b: 3}));
+ checkDedup({
+ $or: [
+ {a: {$gte: 0, $lte: 2}, b: {$gte: 0, $lte: 2}},
+ {a: {$gte: 1, $lte: 3}, b: {$gte: 1, $lte: 3}},
+ {a: {$gte: 1, $lte: 4}, b: {$gte: 1, $lte: 4}}
+ ]
+ },
+ [1, 2, 3, 4, 5]);
-// Deduping multikey
-t.drop();
-t.save({_id: 1, a: [1, 2, 3], b: [4, 5, 6]});
-t.save({_id: 2, a: [1, 2, 3], b: [4, 5, 6]});
-assert.eq(2, t.count());
-checkDedup({$or: [{a: {$in: [1, 2]}}, {b: {$in: [4, 5]}}]}, [1, 2]);
-t.ensureIndex({a: 1});
-checkDedup({$or: [{a: {$in: [1, 2]}}, {b: {$in: [4, 5]}}]}, [1, 2]);
+ // Deduping multikey
+ assert(coll.drop());
+ assert.writeOK(coll.insert({_id: 1, a: [1, 2, 3], b: [4, 5, 6]}));
+ assert.writeOK(coll.insert({_id: 2, a: [1, 2, 3], b: [4, 5, 6]}));
+ assert.eq(2, coll.count());
+
+ checkDedup({$or: [{a: {$in: [1, 2]}}, {b: {$in: [4, 5]}}]}, [1, 2]);
+
+ assert.commandWorked(coll.createIndex({a: 1}));
+ checkDedup({$or: [{a: {$in: [1, 2]}}, {b: {$in: [4, 5]}}]}, [1, 2]);
+}());
diff --git a/jstests/core/fts1.js b/jstests/core/fts1.js
index 5f507733b05..9b95fa8dc14 100644
--- a/jstests/core/fts1.js
+++ b/jstests/core/fts1.js
@@ -1,24 +1,27 @@
// Cannot implicitly shard accessed collections because of extra shard key index in sharded
// collection.
// @tags: [assumes_no_implicit_index_creation]
+(function() {
+ "use strict";
-load("jstests/libs/fts.js");
+ load("jstests/libs/fts.js");
-t = db.text1;
-t.drop();
+ const coll = db.text1;
+ coll.drop();
-t.ensureIndex({x: "text"});
+ assert.commandWorked(coll.createIndex({x: "text"}, {name: "x_text"}));
-assert.eq([], queryIDS(t, "az"), "A0");
+ assert.eq([], queryIDS(coll, "az"), "A0");
-t.save({_id: 1, x: "az b c"});
-t.save({_id: 2, x: "az b"});
-t.save({_id: 3, x: "b c"});
-t.save({_id: 4, x: "b c d"});
+ assert.writeOK(coll.insert({_id: 1, x: "az b c"}));
+ assert.writeOK(coll.insert({_id: 2, x: "az b"}));
+ assert.writeOK(coll.insert({_id: 3, x: "b c"}));
+ assert.writeOK(coll.insert({_id: 4, x: "b c d"}));
-assert.eq([1, 2, 3, 4], queryIDS(t, "c az"), "A1");
-assert.eq([4], queryIDS(t, "d"), "A2");
+ assert.eq([1, 2, 3, 4], queryIDS(coll, "c az").sort(), "A1");
+ assert.eq([4], queryIDS(coll, "d"), "A2");
-idx = t.getIndexes()[1];
-assert(idx.v >= 1, tojson(idx));
-assert(idx.textIndexVersion >= 1, tojson(idx));
+ const index = coll.getIndexes().find(index => index.name === "x_text");
+ assert.neq(index, undefined);
+ assert.gte(index.textIndexVersion, 1, tojson(index));
+}());
diff --git a/jstests/core/geo_distinct.js b/jstests/core/geo_distinct.js
index 4dcc7a7f35f..ad7053f2013 100644
--- a/jstests/core/geo_distinct.js
+++ b/jstests/core/geo_distinct.js
@@ -5,106 +5,111 @@
// Tests distinct with geospatial field values.
// 1. Test distinct with geo values for 'key' (SERVER-2135)
// 2. Test distinct with geo predicates for 'query' (SERVER-13769)
-
-var coll = db.geo_distinct;
-var res;
-
-//
-// 1. Test distinct with geo values for 'key'.
-//
-
-coll.drop();
-coll.insert({loc: {type: 'Point', coordinates: [10, 20]}});
-coll.insert({loc: {type: 'Point', coordinates: [10, 20]}});
-coll.insert({loc: {type: 'Point', coordinates: [20, 30]}});
-coll.insert({loc: {type: 'Point', coordinates: [20, 30]}});
-assert.eq(4, coll.count());
-
-// Test distinct on GeoJSON points with/without a 2dsphere index.
-
-res = coll.runCommand('distinct', {key: 'loc'});
-assert.commandWorked(res);
-assert.eq(res.values.sort(),
- [{type: 'Point', coordinates: [10, 20]}, {type: 'Point', coordinates: [20, 30]}]);
-
-assert.commandWorked(coll.ensureIndex({loc: '2dsphere'}));
-
-res = coll.runCommand('distinct', {key: 'loc'});
-assert.commandWorked(res);
-assert.eq(res.values.sort(),
- [{type: 'Point', coordinates: [10, 20]}, {type: 'Point', coordinates: [20, 30]}]);
-
-// Test distinct on legacy points with/without a 2d index.
-
-// (Note that distinct on a 2d-indexed field doesn't produce a list of coordinate pairs, since
-// distinct logically operates on unique values in an array. Hence, the results are unintuitive and
-// not semantically meaningful.)
-
-coll.dropIndexes();
-
-res = coll.runCommand('distinct', {key: 'loc.coordinates'});
-assert.commandWorked(res);
-assert.eq(res.values.sort(), [10, 20, 30]);
-
-assert.commandWorked(coll.ensureIndex({'loc.coordinates': '2d'}));
-
-res = coll.runCommand('distinct', {key: 'loc.coordinates'});
-assert.commandWorked(res);
-assert.eq(res.values.sort(), [10, 20, 30]);
-
-//
-// 2. Test distinct with geo predicates for 'query'.
-//
-
-coll.drop();
-for (var i = 0; i < 50; ++i) {
- coll.insert({zone: 1, loc: {type: 'Point', coordinates: [-20, -20]}});
- coll.insert({zone: 2, loc: {type: 'Point', coordinates: [-10, -10]}});
- coll.insert({zone: 3, loc: {type: 'Point', coordinates: [0, 0]}});
- coll.insert({zone: 4, loc: {type: 'Point', coordinates: [10, 10]}});
- coll.insert({zone: 5, loc: {type: 'Point', coordinates: [20, 20]}});
-}
-var originGeoJSON = {type: 'Point', coordinates: [0, 0]};
-
-// Test distinct with $nearSphere query predicate.
-
-// A. Unindexed key, no geo index on query predicate.
-res = coll.runCommand(
- 'distinct',
- {key: 'zone', query: {loc: {$nearSphere: {$geometry: originGeoJSON, $maxDistance: 1}}}});
-assert.commandFailed(res);
-// B. Unindexed key, with 2dsphere index on query predicate.
-assert.commandWorked(coll.ensureIndex({loc: '2dsphere'}));
-res = coll.runCommand(
- 'distinct',
- {key: 'zone', query: {loc: {$nearSphere: {$geometry: originGeoJSON, $maxDistance: 1}}}});
-assert.commandWorked(res);
-assert.eq(res.values.sort(), [3]);
-// C. Indexed key, with 2dsphere index on query predicate.
-assert.commandWorked(coll.ensureIndex({zone: 1}));
-res = coll.runCommand(
- 'distinct',
- {key: 'zone', query: {loc: {$nearSphere: {$geometry: originGeoJSON, $maxDistance: 1}}}});
-assert.commandWorked(res);
-assert.eq(res.values.sort(), [3]);
-
-// Test distinct with $near query predicate.
-
-coll.dropIndexes();
-
-// A. Unindexed key, no geo index on query predicate.
-res = coll.runCommand('distinct',
- {key: 'zone', query: {'loc.coordinates': {$near: [0, 0], $maxDistance: 1}}});
-assert.commandFailed(res);
-// B. Unindexed key, with 2d index on query predicate.
-assert.commandWorked(coll.ensureIndex({'loc.coordinates': '2d'}));
-res = coll.runCommand('distinct',
- {key: 'zone', query: {'loc.coordinates': {$near: [0, 0], $maxDistance: 1}}});
-assert.commandWorked(res);
-assert.eq(res.values.sort(), [3]);
-// C. Indexed key, with 2d index on query predicate.
-assert.commandWorked(coll.ensureIndex({zone: 1}));
-res = coll.runCommand('distinct',
- {key: 'zone', query: {'loc.coordinates': {$near: [0, 0], $maxDistance: 1}}});
-assert.commandWorked(res);
-assert.eq(res.values.sort(), [3]);
+(function() {
+ "use strict";
+ const coll = db.geo_distinct;
+ let res;
+
+ //
+ // 1. Test distinct with geo values for 'key'.
+ //
+
+ coll.drop();
+ assert.writeOK(coll.insert({loc: {type: 'Point', coordinates: [10, 20]}}));
+ assert.writeOK(coll.insert({loc: {type: 'Point', coordinates: [10, 20]}}));
+ assert.writeOK(coll.insert({loc: {type: 'Point', coordinates: [20, 30]}}));
+ assert.writeOK(coll.insert({loc: {type: 'Point', coordinates: [20, 30]}}));
+ assert.eq(4, coll.count());
+
+ // Test distinct on GeoJSON points with/without a 2dsphere index.
+
+ res = coll.runCommand('distinct', {key: 'loc'});
+ assert.commandWorked(res);
+ assert.eq(res.values.sort(),
+ [{type: 'Point', coordinates: [10, 20]}, {type: 'Point', coordinates: [20, 30]}]);
+
+ assert.commandWorked(coll.createIndex({loc: '2dsphere'}));
+
+ res = coll.runCommand('distinct', {key: 'loc'});
+ assert.commandWorked(res);
+ assert.eq(res.values.sort(),
+ [{type: 'Point', coordinates: [10, 20]}, {type: 'Point', coordinates: [20, 30]}]);
+
+ // Test distinct on legacy points with/without a 2d index.
+
+ // (Note that distinct on a 2d-indexed field doesn't produce a list of coordinate pairs, since
+ // distinct logically operates on unique values in an array. Hence, the results are unintuitive
+ // and not semantically meaningful.)
+
+ assert.commandWorked(coll.dropIndexes());
+
+ res = coll.runCommand('distinct', {key: 'loc.coordinates'});
+ assert.commandWorked(res);
+ assert.eq(res.values.sort(), [10, 20, 30]);
+
+ assert.commandWorked(coll.createIndex({'loc.coordinates': '2d'}));
+
+ res = coll.runCommand('distinct', {key: 'loc.coordinates'});
+ assert.commandWorked(res);
+ assert.eq(res.values.sort(), [10, 20, 30]);
+
+ //
+ // 2. Test distinct with geo predicates for 'query'.
+ //
+
+ assert(coll.drop());
+ const bulk = coll.initializeUnorderedBulkOp();
+ for (let i = 0; i < 50; ++i) {
+ bulk.insert({zone: 1, loc: {type: 'Point', coordinates: [-20, -20]}});
+ bulk.insert({zone: 2, loc: {type: 'Point', coordinates: [-10, -10]}});
+ bulk.insert({zone: 3, loc: {type: 'Point', coordinates: [0, 0]}});
+ bulk.insert({zone: 4, loc: {type: 'Point', coordinates: [10, 10]}});
+ bulk.insert({zone: 5, loc: {type: 'Point', coordinates: [20, 20]}});
+ }
+ assert.writeOK(bulk.execute());
+
+ const originGeoJSON = {type: 'Point', coordinates: [0, 0]};
+
+ // Test distinct with $nearSphere query predicate.
+
+ // A. Unindexed key, no geo index on query predicate.
+ res = coll.runCommand(
+ 'distinct',
+ {key: 'zone', query: {loc: {$nearSphere: {$geometry: originGeoJSON, $maxDistance: 1}}}});
+ assert.commandFailed(res);
+ // B. Unindexed key, with 2dsphere index on query predicate.
+ assert.commandWorked(coll.createIndex({loc: '2dsphere'}));
+ res = coll.runCommand(
+ 'distinct',
+ {key: 'zone', query: {loc: {$nearSphere: {$geometry: originGeoJSON, $maxDistance: 1}}}});
+ assert.commandWorked(res);
+ assert.eq(res.values.sort(), [3]);
+ // C. Indexed key, with 2dsphere index on query predicate.
+ assert.commandWorked(coll.createIndex({zone: 1}));
+ res = coll.runCommand(
+ 'distinct',
+ {key: 'zone', query: {loc: {$nearSphere: {$geometry: originGeoJSON, $maxDistance: 1}}}});
+ assert.commandWorked(res);
+ assert.eq(res.values.sort(), [3]);
+
+ // Test distinct with $near query predicate.
+
+ assert.commandWorked(coll.dropIndexes());
+
+ // A. Unindexed key, no geo index on query predicate.
+ res = coll.runCommand(
+ 'distinct', {key: 'zone', query: {'loc.coordinates': {$near: [0, 0], $maxDistance: 1}}});
+ assert.commandFailed(res);
+ // B. Unindexed key, with 2d index on query predicate.
+ assert.commandWorked(coll.createIndex({'loc.coordinates': '2d'}));
+ res = coll.runCommand(
+ 'distinct', {key: 'zone', query: {'loc.coordinates': {$near: [0, 0], $maxDistance: 1}}});
+ assert.commandWorked(res);
+ assert.eq(res.values.sort(), [3]);
+ // C. Indexed key, with 2d index on query predicate.
+ assert.commandWorked(coll.createIndex({zone: 1}));
+ res = coll.runCommand(
+ 'distinct', {key: 'zone', query: {'loc.coordinates': {$near: [0, 0], $maxDistance: 1}}});
+ assert.commandWorked(res);
+ assert.eq(res.values.sort(), [3]);
+}());
diff --git a/jstests/core/geo_s2ordering.js b/jstests/core/geo_s2ordering.js
index 026fdda62c6..165ccd07d96 100644
--- a/jstests/core/geo_s2ordering.js
+++ b/jstests/core/geo_s2ordering.js
@@ -2,51 +2,57 @@
// actually matters for lookup speed. That is, if we're looking for a non-geo key of which
// there are not many, the index order (nongeo, geo) should be faster than (geo, nongeo)
// for 2dsphere.
-t = db.geo_s2ordering;
-t.drop();
-
-needle = "hari";
-
-// We insert lots of points in a region and look for a non-geo key which is rare.
-function makepoints(needle) {
- lat = 0;
- lng = 0;
- points = 50.0;
- var bulk = t.initializeUnorderedBulkOp();
- for (var x = -points; x < points; x += 1) {
- for (var y = -points; y < points; y += 1) {
- tag = x.toString() + "," + y.toString();
- bulk.insert({
- nongeo: tag,
- geo: {type: "Point", coordinates: [lng + x / points, lat + y / points]}
- });
+(function() {
+ "use strict";
+
+ const coll = db.geo_s2ordering;
+ coll.drop();
+
+ const needle = "hari";
+
+ // We insert lots of points in a region and look for a non-geo key which is rare.
+ function makepoints(needle) {
+ const lat = 0;
+ const lng = 0;
+ const points = 50.0;
+
+ const bulk = coll.initializeUnorderedBulkOp();
+ for (let x = -points; x < points; x += 1) {
+ for (let y = -points; y < points; y += 1) {
+ bulk.insert({
+ nongeo: x.toString() + "," + y.toString(),
+ geo: {type: "Point", coordinates: [lng + x / points, lat + y / points]}
+ });
+ }
}
+ bulk.insert({nongeo: needle, geo: {type: "Point", coordinates: [0, 0]}});
+ assert.writeOK(bulk.execute());
+ }
+
+ function runTest(index) {
+ assert.commandWorked(coll.ensureIndex(index));
+ const cursor =
+ coll.find({nongeo: needle, geo: {$within: {$centerSphere: [[0, 0], Math.PI / 180.0]}}});
+ const stats = cursor.explain("executionStats").executionStats;
+ assert.commandWorked(coll.dropIndex(index));
+ return stats;
}
- bulk.insert({nongeo: needle, geo: {type: "Point", coordinates: [0, 0]}});
- assert.writeOK(bulk.execute());
-}
-
-function runTest(index) {
- t.ensureIndex(index);
- var resultcount = 0;
- var cursor =
- t.find({nongeo: needle, geo: {$within: {$centerSphere: [[0, 0], Math.PI / 180.0]}}});
-
- var stats = cursor.explain("executionStats").executionStats;
- t.dropIndex(index);
- return stats;
-}
-
-makepoints(needle);
-// Indexing non-geo first should be quicker.
-fast = runTest({nongeo: 1, geo: "2dsphere"});
-slow = runTest({geo: "2dsphere", nongeo: 1});
-// The nReturned should be the same
-assert.eq(fast.nReturned, 1);
-assert.eq(slow.nReturned, 1);
-// Only one document is examined, since we use index.
-assert.eq(fast.totalDocsExamined, 1);
-assert.eq(slow.totalDocsExamined, 1);
-// The ordering actually matters for lookup speed.
-// totalKeysExamined is a direct measure of its speed.
-assert.lt(fast.totalKeysExamined, slow.totalKeysExamined);
+
+ makepoints(needle);
+
+ // Indexing non-geo first should be quicker.
+ const fast = runTest({nongeo: 1, geo: "2dsphere"});
+ const slow = runTest({geo: "2dsphere", nongeo: 1});
+
+ // The nReturned should be the same.
+ assert.eq(fast.nReturned, 1);
+ assert.eq(slow.nReturned, 1);
+
+ // Only one document is examined, since we use the index.
+ assert.eq(fast.totalDocsExamined, 1);
+ assert.eq(slow.totalDocsExamined, 1);
+
+ // The ordering actually matters for lookup speed.
+ // totalKeysExamined is a direct measure of its speed.
+ assert.lt(fast.totalKeysExamined, slow.totalKeysExamined);
+}());
diff --git a/jstests/core/group1.js b/jstests/core/group1.js
index 70a266e2a55..c6fd0fdf16d 100644
--- a/jstests/core/group1.js
+++ b/jstests/core/group1.js
@@ -1,146 +1,151 @@
// Cannot implicitly shard accessed collections because of unsupported group operator on sharded
// collection.
// @tags: [assumes_unsharded_collection]
-
-t = db.group1;
-t.drop();
-
-t.save({n: 1, a: 1});
-t.save({n: 2, a: 1});
-t.save({n: 3, a: 2});
-t.save({n: 4, a: 2});
-t.save({n: 5, a: 2});
-
-var p = {
- key: {a: true},
- reduce: function(obj, prev) {
- prev.count++;
- },
- initial: {count: 0}
-};
-
-res = t.group(p);
-
-assert(res.length == 2, "A");
-assert(res[0].a == 1, "B");
-assert(res[0].count == 2, "C");
-assert(res[1].a == 2, "D");
-assert(res[1].count == 3, "E");
-
-assert.eq(res, t.groupcmd(p), "ZZ");
-
-ret = t.groupcmd({key: {}, reduce: p.reduce, initial: p.initial});
-assert.eq(1, ret.length, "ZZ 2");
-assert.eq(5, ret[0].count, "ZZ 3");
-
-ret = t.groupcmd({
- key: {},
- reduce: function(obj, prev) {
- prev.sum += obj.n;
- },
- initial: {sum: 0}
-});
-assert.eq(1, ret.length, "ZZ 4");
-assert.eq(15, ret[0].sum, "ZZ 5");
-
-t.drop();
-
-t.save({"a": 2});
-t.save({"b": 5});
-t.save({"a": 1});
-t.save({"a": 2});
-
-c = {
- key: {a: 1},
- cond: {},
- initial: {"count": 0},
- reduce: function(obj, prev) {
- prev.count++;
- }
-};
-
-assert.eq(t.group(c), t.groupcmd(c), "ZZZZ");
-
-t.drop();
-
-t.save({name: {first: "a", last: "A"}});
-t.save({name: {first: "b", last: "B"}});
-t.save({name: {first: "a", last: "A"}});
-
-p = {
- key: {'name.first': true},
- reduce: function(obj, prev) {
- prev.count++;
- },
- initial: {count: 0}
-};
-
-res = t.group(p);
-assert.eq(2, res.length, "Z1");
-assert.eq("a", res[0]['name.first'], "Z2");
-assert.eq("b", res[1]['name.first'], "Z3");
-assert.eq(2, res[0].count, "Z4");
-assert.eq(1, res[1].count, "Z5");
-
-// SERVER-15851 Test invalid user input.
-p = {
- ns: "group1",
- key: {"name.first": true},
- $reduce: function(obj, prev) {
- prev.count++;
- },
- initial: {count: 0},
- finalize: "abc"
-};
-assert.commandFailedWithCode(
- db.runCommand({group: p}), ErrorCodes.JSInterpreterFailure, "Illegal finalize function");
-
-p = {
- ns: "group1",
- key: {"name.first": true},
- $reduce: function(obj, prev) {
- prev.count++;
- },
- initial: {count: 0},
- finalize: function(obj) {
- throw new Error("Intentionally throwing exception in finalize function");
+(function() {
+ "use strict";
+
+ const coll = db.group1;
+ coll.drop();
+
+ assert.writeOK(coll.insert({n: 1, a: 1}));
+ assert.writeOK(coll.insert({n: 2, a: 1}));
+ assert.writeOK(coll.insert({n: 3, a: 2}));
+ assert.writeOK(coll.insert({n: 4, a: 2}));
+ assert.writeOK(coll.insert({n: 5, a: 2}));
+
+ let p = {
+ key: {a: true},
+ reduce: function(obj, prev) {
+ prev.count++;
+ },
+ initial: {count: 0}
+ };
+
+ function sortFuncGenerator(key) {
+ return (doc1, doc2) => {
+ if (doc1[key] < doc2[key]) {
+ return -1;
+ } else if (doc1[key] > doc2[key]) {
+ return 1;
+ } else {
+ return 0;
+ }
+ };
}
-};
-assert.commandFailedWithCode(
- db.runCommand({group: p}), ErrorCodes.JSInterpreterFailure, "Illegal finalize function 2");
-
-p = {
- ns: "group1",
- $keyf: "a",
- $reduce: function(obj, prev) {
- prev.count++;
- },
- initial: {count: 0},
- finalize: function(obj) {
- throw new Error("Intentionally throwing exception in finalize function");
- }
-};
-assert.commandFailedWithCode(
- db.runCommand({group: p}), ErrorCodes.JSInterpreterFailure, "Illegal keyf function");
-
-p = {
- ns: "group1",
- key: {"name.first": true},
- $reduce: "abc",
- initial: {count: 0}
-};
-assert.commandFailedWithCode(
- db.runCommand({group: p}), ErrorCodes.JSInterpreterFailure, "Illegal reduce function");
-
-p = {
- ns: "group1",
- key: {"name.first": true},
- $reduce: function(obj, pre) {
- prev.count++;
- },
- initial: {count: 0}
-};
-assert.commandFailedWithCode(
- db.runCommand({group: p}), ErrorCodes.JSInterpreterFailure, "Illegal reduce function 2");
-
-t.drop();
+
+ const sortOnA = sortFuncGenerator("a");
+ let expected = [{a: 1, count: 2}, {a: 2, count: 3}];
+ let result = coll.group(p).sort(sortOnA);
+ assert.eq(result, expected);
+
+ result = coll.groupcmd(p).sort(sortOnA);
+ assert.eq(result, expected);
+
+ expected = [{count: 5}];
+ result = coll.groupcmd({key: {}, reduce: p.reduce, initial: p.initial});
+ assert.eq(result, expected);
+
+ expected = [{sum: 15}];
+ result = coll.groupcmd({
+ key: {},
+ reduce: function(obj, prev) {
+ prev.sum += obj.n;
+ },
+ initial: {sum: 0}
+ });
+ assert.eq(result, expected);
+
+ assert(coll.drop());
+
+ assert.writeOK(coll.insert({"a": 2}));
+ assert.writeOK(coll.insert({"b": 5}));
+ assert.writeOK(coll.insert({"a": 1}));
+ assert.writeOK(coll.insert({"a": 2}));
+
+ const c = {
+ key: {a: 1},
+ cond: {},
+ initial: {"count": 0},
+ reduce: function(obj, prev) {
+ prev.count++;
+ }
+ };
+
+ expected = [{a: null, count: 1}, {a: 1, count: 1}, {a: 2, count: 2}];
+ assert.eq(coll.group(c).sort(sortOnA), expected);
+ assert.eq(coll.groupcmd(c).sort(sortOnA), expected);
+
+ assert(coll.drop());
+
+ assert.writeOK(coll.insert({name: {first: "a", last: "A"}}));
+ assert.writeOK(coll.insert({name: {first: "b", last: "B"}}));
+ assert.writeOK(coll.insert({name: {first: "a", last: "A"}}));
+
+ p = {
+ key: {'name.first': true},
+ reduce: function(obj, prev) {
+ prev.count++;
+ },
+ initial: {count: 0}
+ };
+ const sortOnNameDotFirst = sortFuncGenerator("name.first");
+
+ expected = [{"name.first": "a", count: 2}, {"name.first": "b", count: 1}];
+ assert.eq(coll.group(p).sort(sortOnNameDotFirst), expected);
+
+ // SERVER-15851 Test invalid user input.
+ p = {
+ ns: "group1",
+ key: {"name.first": true},
+ $reduce: function(obj, prev) {
+ prev.count++;
+ },
+ initial: {count: 0},
+ finalize: "abc"
+ };
+ assert.commandFailedWithCode(
+ db.runCommand({group: p}), ErrorCodes.JSInterpreterFailure, "Illegal finalize function");
+
+ p = {
+ ns: "group1",
+ key: {"name.first": true},
+ $reduce: function(obj, prev) {
+ prev.count++;
+ },
+ initial: {count: 0},
+ finalize: function(obj) {
+ throw new Error("Intentionally throwing exception in finalize function");
+ }
+ };
+ assert.commandFailedWithCode(
+ db.runCommand({group: p}), ErrorCodes.JSInterpreterFailure, "Illegal finalize function 2");
+
+ p = {
+ ns: "group1",
+ $keyf: "a",
+ $reduce: function(obj, prev) {
+ prev.count++;
+ },
+ initial: {count: 0},
+ finalize: function(obj) {
+ throw new Error("Intentionally throwing exception in finalize function");
+ }
+ };
+ assert.commandFailedWithCode(
+ db.runCommand({group: p}), ErrorCodes.JSInterpreterFailure, "Illegal keyf function");
+
+ p = {ns: "group1", key: {"name.first": true}, $reduce: "abc", initial: {count: 0}};
+ assert.commandFailedWithCode(
+ db.runCommand({group: p}), ErrorCodes.JSInterpreterFailure, "Illegal reduce function");
+
+ p = {
+ ns: "group1",
+ key: {"name.first": true},
+ $reduce: function(obj, pre) {
+ prev.count++;
+ },
+ initial: {count: 0}
+ };
+ assert.commandFailedWithCode(
+ db.runCommand({group: p}), ErrorCodes.JSInterpreterFailure, "Illegal reduce function 2");
+}());
diff --git a/jstests/core/group2.js b/jstests/core/group2.js
index 5dc0ddce93d..26f65c3d8f8 100644
--- a/jstests/core/group2.js
+++ b/jstests/core/group2.js
@@ -1,45 +1,43 @@
// Cannot implicitly shard accessed collections because of unsupported group operator on sharded
// collection.
// @tags: [assumes_unsharded_collection]
-
-t = db.group2;
-t.drop();
-
-t.save({a: 2});
-t.save({b: 5});
-t.save({a: 1});
-
-cmd = {
- key: {a: 1},
- initial: {count: 0},
- reduce: function(obj, prev) {
- prev.count++;
- }
-};
-
-result = t.group(cmd);
-
-assert.eq(3, result.length, "A");
-assert.eq(null, result[1].a, "C");
-assert("a" in result[1], "D");
-assert.eq(1, result[2].a, "E");
-
-assert.eq(1, result[0].count, "F");
-assert.eq(1, result[1].count, "G");
-assert.eq(1, result[2].count, "H");
-
-var keyFn = function(x) {
- return {a: 'a' in x ? x.a : null};
-};
-
-delete cmd.key;
-cmd["$keyf"] = keyFn;
-result2 = t.group(cmd);
-
-assert.eq(result, result2, "check result2");
-
-delete cmd.$keyf;
-cmd["keyf"] = keyFn;
-result3 = t.group(cmd);
-
-assert.eq(result, result3, "check result3");
+(function() {
+ "use strict";
+ const coll = db.group2;
+ coll.drop();
+
+ assert.writeOK(coll.insert({a: 2}));
+ assert.writeOK(coll.insert({b: 5}));
+ assert.writeOK(coll.insert({a: 1}));
+
+ const cmd = {
+ key: {a: 1},
+ initial: {count: 0},
+ reduce: function(obj, prev) {
+ prev.count++;
+ }
+ };
+ const sortFunc = function(doc1, doc2) {
+ if (doc1.a < doc2.a) {
+ return -1;
+ } else if (doc1.a > doc2.a) {
+ return 1;
+ } else {
+ return 0;
+ }
+ };
+ const expected = [{a: null, count: 1}, {a: 1, count: 1}, {a: 2, count: 1}];
+ assert.eq(coll.group(cmd).sort(sortFunc), expected);
+
+ const keyFn = function(x) {
+ return {a: 'a' in x ? x.a : null};
+ };
+
+ delete cmd.key;
+ cmd["$keyf"] = keyFn;
+ assert.eq(coll.group(cmd).sort(sortFunc), expected);
+
+ delete cmd.$keyf;
+ cmd["keyf"] = keyFn;
+ assert.eq(coll.group(cmd).sort(sortFunc), expected);
+}());
diff --git a/jstests/core/maxscan.js b/jstests/core/maxscan.js
index a862ed426a0..37cbf4b5b2f 100644
--- a/jstests/core/maxscan.js
+++ b/jstests/core/maxscan.js
@@ -1,18 +1,21 @@
+(function() {
+ "use strict";
-t = db.maxscan;
-t.drop();
+ const coll = db.maxscan;
+ coll.drop();
-N = 100;
-for (i = 0; i < N; i++) {
- t.insert({_id: i, x: i % 10});
-}
+ const N = 100;
+ for (let i = 0; i < N; i++) {
+ assert.writeOK(coll.insert({_id: i, x: i % 10}));
+ }
-assert.eq(N, t.find().itcount(), "A");
-assert.eq(50, t.find().maxScan(50).itcount(), "B");
+ assert.eq(N, coll.find().itcount(), "A");
+ assert.eq(50, coll.find().maxScan(50).itcount(), "B");
-assert.eq(10, t.find({x: 2}).itcount(), "C");
-assert.eq(5, t.find({x: 2}).maxScan(50).itcount(), "D");
+ assert.eq(10, coll.find({x: 2}).itcount(), "C");
+ assert.eq(5, coll.find({x: 2}).sort({_id: 1}).maxScan(50).itcount(), "D");
-t.ensureIndex({x: 1});
-assert.eq(10, t.find({x: 2}).hint({x: 1}).maxScan(N).itcount(), "E");
-assert.eq(0, t.find({x: 2}).hint({x: 1}).maxScan(1).itcount(), "E");
+ assert.commandWorked(coll.ensureIndex({x: 1}));
+ assert.eq(10, coll.find({x: 2}).sort({_id: 1}).hint({x: 1}).maxScan(N).itcount(), "E");
+ assert.eq(0, coll.find({x: 2}).sort({_id: 1}).hint({x: 1}).maxScan(1).itcount(), "E");
+}());
diff --git a/jstests/core/nan.js b/jstests/core/nan.js
index 611f3d14a6a..1b34a53e64d 100644
--- a/jstests/core/nan.js
+++ b/jstests/core/nan.js
@@ -1,66 +1,60 @@
-// Test basic NaN handling.
-
-var t = db.jstests_nan;
-t.drop();
-
-var cursor;
-
-t.insert({_id: 0, a: -Infinity});
-t.insert({_id: 1, a: -3});
-t.insert({_id: 2, a: 0});
-t.insert({_id: 3, a: 3});
-t.insert({_id: 4, a: Infinity});
-// WiredTiger indexes handle -NaN and NaN differently.
-t.insert({_id: 5, a: NaN});
-t.insert({_id: 6, a: -NaN});
-t.insert({_id: 7, a: undefined});
-t.insert({_id: 8, a: null});
-t.insert({_id: 9, a: []});
-t.insert({_id: 10, a: {b: 1}});
-t.insert({_id: 11, a: {b: 1}});
-
/**
- * Ensures correct results for EQ, LT, LTE, GT, and GTE cases.
+ * Tests basic NaN handling. Note that WiredTiger indexes handle -NaN and NaN differently.
*/
-var testNaNComparisons = function() {
- // EQ
- cursor = t.find({a: NaN});
- assert.eq(5, cursor.next()["_id"]);
- assert.eq(6, cursor.next()["_id"]);
- assert(!cursor.hasNext());
-
- // LT
- cursor = t.find({a: {$lt: NaN}});
- assert(!cursor.hasNext());
-
- // LTE
- cursor = t.find({a: {$lte: NaN}});
- var id1 = cursor.next()["_id"];
- var id2 = cursor.next()["_id"];
- // Exactly one of the two conditions must be true.
- var cond1 = id1 === 5 && id2 === 6;
- var cond2 = id1 === 6 && id2 === 5;
- assert(cond1 ^ cond2);
- assert(!cursor.hasNext());
-
- // GT
- cursor = t.find({a: {$gt: NaN}});
- assert(!cursor.hasNext());
-
- // GTE
- cursor = t.find({a: {$gte: NaN}});
- var id1 = cursor.next()["_id"];
- var id2 = cursor.next()["_id"];
- // Exactly one of the two conditions must be true.
- var cond1 = id1 === 5 && id2 === 6;
- var cond2 = id1 === 6 && id2 === 5;
- assert(cond1 ^ cond2);
- assert(!cursor.hasNext());
-};
-
-// Unindexed
-testNaNComparisons();
-
-// Indexed
-t.ensureIndex({a: 1});
-testNaNComparisons();
+(function() {
+ "use strict";
+
+ const coll = db.jstests_nan;
+ coll.drop();
+
+ assert.writeOK(coll.insert({_id: 0, a: -Infinity}));
+ assert.writeOK(coll.insert({_id: 1, a: -3}));
+ assert.writeOK(coll.insert({_id: 2, a: 0}));
+ assert.writeOK(coll.insert({_id: 3, a: 3}));
+ assert.writeOK(coll.insert({_id: 4, a: Infinity}));
+ assert.writeOK(coll.insert({_id: 5, a: NaN}));
+ assert.writeOK(coll.insert({_id: 6, a: -NaN}));
+ assert.writeOK(coll.insert({_id: 7, a: undefined}));
+ assert.writeOK(coll.insert({_id: 8, a: null}));
+ assert.writeOK(coll.insert({_id: 9, a: []}));
+ assert.writeOK(coll.insert({_id: 10, a: {b: 1}}));
+ assert.writeOK(coll.insert({_id: 11, a: {b: 1}}));
+
+ /**
+ * Ensures correct results for EQ, LT, LTE, GT, and GTE cases.
+ */
+ var testNaNComparisons = function() {
+ // EQ
+ let cursor = coll.find({a: NaN}).sort({_id: 1});
+ assert.eq(5, cursor.next()["_id"]);
+ assert.eq(6, cursor.next()["_id"]);
+ assert(!cursor.hasNext());
+
+ // LT
+ cursor = coll.find({a: {$lt: NaN}});
+ assert(!cursor.hasNext());
+
+ // LTE
+ cursor = coll.find({a: {$lte: NaN}}).sort({_id: 1});
+ assert.eq(5, cursor.next()["_id"]);
+ assert.eq(6, cursor.next()["_id"]);
+ assert(!cursor.hasNext());
+
+ // GT
+ cursor = coll.find({a: {$gt: NaN}});
+ assert(!cursor.hasNext());
+
+ // GTE
+ cursor = coll.find({a: {$gte: NaN}}).sort({_id: 1});
+ assert.eq(5, cursor.next()["_id"]);
+ assert.eq(6, cursor.next()["_id"]);
+ assert(!cursor.hasNext());
+ };
+
+ // Unindexed.
+ testNaNComparisons();
+
+ // Indexed.
+ assert.commandWorked(coll.createIndex({a: 1}));
+ testNaNComparisons();
+}());
diff --git a/jstests/core/not2.js b/jstests/core/not2.js
index 98eb19cee6f..a02399139df 100644
--- a/jstests/core/not2.js
+++ b/jstests/core/not2.js
@@ -1,84 +1,86 @@
-t = db.jstests_not2;
-t.drop();
+(function() {
+ "use strict";
-check = function(query, expected, size) {
- if (size == null) {
- size = 1;
- }
- assert.eq(size, t.find(query).itcount(), tojson(query));
- if (size > 0) {
- assert.eq(expected, t.findOne(query).i, tojson(query));
+ const coll = db.jstests_not2;
+ coll.drop();
+
+ function check(query, expected, size) {
+ if (size === undefined) {
+ size = 1;
+ }
+ assert.eq(size, coll.find(query).itcount(), tojson(query));
+ if (size > 0) {
+ const cursor = coll.find(query).sort({i: 1});
+ assert.eq(expected, cursor.toArray()[0].i, tojson(query));
+ }
}
-};
-fail = function(query) {
- try {
- t.find(query).itcount();
- assert(false, tojson(query));
- } catch (e) {
- // expected
+ function fail(query) {
+ assert.throws(() => coll.find(query).itcount());
}
-};
-doTest = function() {
+ function doTest() {
+ assert.writeOK(coll.remove({}));
- t.remove({});
+ assert.writeOK(coll.insert({i: "a"}));
+ assert.writeOK(coll.insert({i: "b"}));
- t.save({i: "a"});
- t.save({i: "b"});
+ // TODO SERVER-12735: We currently do not handle double negatives during query
+ // canonicalization.
+ fail({i: {$not: {$not: "a"}}});
+ check({i: {$not: {$not: {$gt: "a"}}}}, "b");
- fail({i: {$not: "a"}});
- // SERVER-12735: We currently do not handle double negatives
- // during query canonicalization.
- // fail( {i:{$not:{$not:"a"}}} );
- // fail( {i:{$not:{$not:{$gt:"a"}}}} );
- fail({i: {$not: {$ref: "foo"}}});
- fail({i: {$not: {}}});
- check({i: {$gt: "a"}}, "b");
- check({i: {$not: {$gt: "a"}}}, "a");
- check({i: {$not: {$ne: "a"}}}, "a");
- check({i: {$not: {$gte: "b"}}}, "a");
- check({i: {$exists: true}}, "a", 2);
- check({i: {$not: {$exists: true}}}, "", 0);
- check({j: {$not: {$exists: false}}}, "", 0);
- check({j: {$not: {$exists: true}}}, "a", 2);
- check({i: {$not: {$in: ["a"]}}}, "b");
- check({i: {$not: {$in: ["a", "b"]}}}, "", 0);
- check({i: {$not: {$in: ["g"]}}}, "a", 2);
- check({i: {$not: {$nin: ["a"]}}}, "a");
- check({i: {$not: /a/}}, "b");
- check({i: {$not: /(a|b)/}}, "", 0);
- check({i: {$not: /a/, $regex: "a"}}, "", 0);
- check({i: {$not: /aa/}}, "a", 2);
- fail({i: {$not: {$regex: "a"}}});
- fail({i: {$not: {$options: "a"}}});
- check({i: {$type: 2}}, "a", 2);
- check({i: {$not: {$type: 1}}}, "a", 2);
- check({i: {$not: {$type: 2}}}, "", 0);
+ fail({i: {$not: "a"}});
+ fail({i: {$not: {$ref: "foo"}}});
+ fail({i: {$not: {}}});
+ check({i: {$gt: "a"}}, "b");
+ check({i: {$not: {$gt: "a"}}}, "a");
+ check({i: {$not: {$ne: "a"}}}, "a");
+ check({i: {$not: {$gte: "b"}}}, "a");
+ check({i: {$exists: true}}, "a", 2);
+ check({i: {$not: {$exists: true}}}, "", 0);
+ check({j: {$not: {$exists: false}}}, "", 0);
+ check({j: {$not: {$exists: true}}}, "a", 2);
+ check({i: {$not: {$in: ["a"]}}}, "b");
+ check({i: {$not: {$in: ["a", "b"]}}}, "", 0);
+ check({i: {$not: {$in: ["g"]}}}, "a", 2);
+ check({i: {$not: {$nin: ["a"]}}}, "a");
+ check({i: {$not: /a/}}, "b");
+ check({i: {$not: /(a|b)/}}, "", 0);
+ check({i: {$not: /a/, $regex: "a"}}, "", 0);
+ check({i: {$not: /aa/}}, "a", 2);
+ fail({i: {$not: {$regex: "a"}}});
+ fail({i: {$not: {$options: "a"}}});
+ check({i: {$type: 2}}, "a", 2);
+ check({i: {$not: {$type: 1}}}, "a", 2);
+ check({i: {$not: {$type: 2}}}, "", 0);
- t.remove({});
- t.save({i: 1});
- check({i: {$not: {$mod: [5, 1]}}}, null, 0);
- check({i: {$mod: [5, 2]}}, null, 0);
- check({i: {$not: {$mod: [5, 2]}}}, 1, 1);
+ assert.writeOK(coll.remove({}));
+ assert.writeOK(coll.insert({i: 1}));
+ check({i: {$not: {$mod: [5, 1]}}}, null, 0);
+ check({i: {$mod: [5, 2]}}, null, 0);
+ check({i: {$not: {$mod: [5, 2]}}}, 1, 1);
- t.remove({});
- t.save({i: ["a", "b"]});
- check({i: {$not: {$size: 2}}}, null, 0);
- check({i: {$not: {$size: 3}}}, ["a", "b"]);
- check({i: {$not: {$gt: "a"}}}, null, 0);
- check({i: {$not: {$gt: "c"}}}, ["a", "b"]);
- check({i: {$not: {$all: ["a", "b"]}}}, null, 0);
- check({i: {$not: {$all: ["c"]}}}, ["a", "b"]);
+ assert.writeOK(coll.remove({}));
+ assert.writeOK(coll.insert({i: ["a", "b"]}));
+ check({i: {$not: {$size: 2}}}, null, 0);
+ check({i: {$not: {$size: 3}}}, ["a", "b"]);
+ check({i: {$not: {$gt: "a"}}}, null, 0);
+ check({i: {$not: {$gt: "c"}}}, ["a", "b"]);
+ check({i: {$not: {$all: ["a", "b"]}}}, null, 0);
+ check({i: {$not: {$all: ["c"]}}}, ["a", "b"]);
- t.remove({});
- t.save({i: [{j: "a"}]});
- t.save({i: [{j: "b"}]});
- check({i: {$not: {$elemMatch: {j: "a"}}}}, [{j: "b"}]);
- check({i: {$not: {$elemMatch: {j: "f"}}}}, [{j: "a"}], 2);
+ assert.writeOK(coll.remove({}));
+ assert.writeOK(coll.insert({i: [{j: "a"}]}));
+ assert.writeOK(coll.insert({i: [{j: "b"}]}));
+ check({i: {$not: {$elemMatch: {j: "a"}}}}, [{j: "b"}]);
+ check({i: {$not: {$elemMatch: {j: "f"}}}}, [{j: "a"}], 2);
+ }
-};
+ // Run the test without any index.
+ doTest();
-doTest();
-t.ensureIndex({i: 1});
-doTest();
+ // Run the test with an index present.
+ assert.commandWorked(coll.ensureIndex({i: 1}));
+ doTest();
+}());
diff --git a/jstests/core/sort3.js b/jstests/core/sort3.js
index 933f16da6cb..1a1df005fb3 100644
--- a/jstests/core/sort3.js
+++ b/jstests/core/sort3.js
@@ -1,17 +1,13 @@
-t = db.sort3;
-t.drop();
+(function() {
+ "use strict";
-t.save({a: 1});
-t.save({a: 5});
-t.save({a: 3});
+ const coll = db.sort3;
+ coll.drop();
-assert.eq("1,5,3", t.find().toArray().map(function(z) {
- return z.a;
-}));
+ assert.writeOK(coll.insert({a: 1}));
+ assert.writeOK(coll.insert({a: 5}));
+ assert.writeOK(coll.insert({a: 3}));
-assert.eq("1,3,5", t.find().sort({a: 1}).toArray().map(function(z) {
- return z.a;
-}));
-assert.eq("5,3,1", t.find().sort({a: -1}).toArray().map(function(z) {
- return z.a;
-}));
+ assert.eq([1, 3, 5], coll.find().sort({a: 1}).toArray().map(doc => doc.a));
+ assert.eq([5, 3, 1], coll.find().sort({a: -1}).toArray().map(doc => doc.a));
+}());
diff --git a/jstests/core/sort4.js b/jstests/core/sort4.js
index 41b4e25fe11..ef33e779d8e 100644
--- a/jstests/core/sort4.js
+++ b/jstests/core/sort4.js
@@ -1,40 +1,45 @@
-t = db.sort4;
-t.drop();
-
-function nice(sort, correct, extra) {
- var c = t.find().sort(sort);
- var s = "";
- c.forEach(function(z) {
- if (s.length)
- s += ",";
- s += z.name;
- if (z.prename)
- s += z.prename;
- });
- print(tojson(sort) + "\t" + s);
- if (correct)
- assert.eq(correct, s, tojson(sort) + "(" + extra + ")");
- return s;
-}
-
-t.save({name: 'A', prename: 'B'});
-t.save({name: 'A', prename: 'C'});
-t.save({name: 'B', prename: 'B'});
-t.save({name: 'B', prename: 'D'});
-
-nice({name: 1}, "AB,AC,BB,BD", "s1");
-nice({prename: 1}, "AB,BB,AC,BD", "s2");
-nice({name: 1, prename: 1}, "AB,AC,BB,BD", "s3");
-
-t.save({name: 'A'});
-nice({name: 1, prename: 1}, "A,AB,AC,BB,BD", "e1");
-
-t.save({name: 'C'});
-nice({name: 1, prename: 1}, "A,AB,AC,BB,BD,C", "e2"); // SERVER-282
-
-t.ensureIndex({name: 1, prename: 1});
-nice({name: 1, prename: 1}, "A,AB,AC,BB,BD,C", "e2ia"); // SERVER-282
-
-t.dropIndexes();
-t.ensureIndex({name: 1});
-nice({name: 1, prename: 1}, "A,AB,AC,BB,BD,C", "e2ib"); // SERVER-282
+(function() {
+ "use strict";
+
+ const coll = db.sort4;
+ coll.drop();
+
+ function nice(sort, correct, extra) {
+ const c = coll.find().sort(sort);
+ let s = "";
+ c.forEach(function(z) {
+ if (s.length) {
+ s += ",";
+ }
+ s += z.name;
+ if (z.prename) {
+ s += z.prename;
+ }
+ });
+ if (correct) {
+ assert.eq(correct, s, tojson(sort) + "(" + extra + ")");
+ }
+ return s;
+ }
+
+ assert.writeOK(coll.insert({name: 'A', prename: 'B'}));
+ assert.writeOK(coll.insert({name: 'A', prename: 'C'}));
+ assert.writeOK(coll.insert({name: 'B', prename: 'B'}));
+ assert.writeOK(coll.insert({name: 'B', prename: 'D'}));
+
+ nice({name: 1, prename: 1}, "AB,AC,BB,BD", "s3");
+ nice({prename: 1, name: 1}, "AB,BB,AC,BD", "s3");
+
+ assert.writeOK(coll.insert({name: 'A'}));
+ nice({name: 1, prename: 1}, "A,AB,AC,BB,BD", "e1");
+
+ assert.writeOK(coll.insert({name: 'C'}));
+ nice({name: 1, prename: 1}, "A,AB,AC,BB,BD,C", "e2"); // SERVER-282
+
+ assert.commandWorked(coll.ensureIndex({name: 1, prename: 1}));
+ nice({name: 1, prename: 1}, "A,AB,AC,BB,BD,C", "e2ia"); // SERVER-282
+
+ assert.commandWorked(coll.dropIndexes());
+ assert.commandWorked(coll.ensureIndex({name: 1}));
+ nice({name: 1, prename: 1}, "A,AB,AC,BB,BD,C", "e2ib"); // SERVER-282
+}());