summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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
+}());