diff options
author | Ian Boros <puppyofkosh@gmail.com> | 2019-04-04 19:20:35 -0400 |
---|---|---|
committer | Ian Boros <puppyofkosh@gmail.com> | 2019-04-11 18:34:10 -0400 |
commit | 502df279c7476c01758ab210728f4acc4a27a218 (patch) | |
tree | f350da86174a673c792ca99e16ae43a0319e71c8 /jstests/core | |
parent | d131d7861c73efe052c5909ae8f1452c100a461d (diff) | |
download | mongo-502df279c7476c01758ab210728f4acc4a27a218.tar.gz |
SERVER-39567 Change find min/max options to require hint
Diffstat (limited to 'jstests/core')
-rw-r--r-- | jstests/core/collation.js | 24 | ||||
-rw-r--r-- | jstests/core/explain_find.js | 8 | ||||
-rw-r--r-- | jstests/core/explain_shell_helpers.js | 8 | ||||
-rw-r--r-- | jstests/core/min_max_bounds.js | 8 | ||||
-rw-r--r-- | jstests/core/min_max_hashed_index.js | 18 | ||||
-rw-r--r-- | jstests/core/minmax.js | 109 | ||||
-rw-r--r-- | jstests/core/minmax_edge.js | 371 | ||||
-rw-r--r-- | jstests/core/profile_find.js | 4 | ||||
-rw-r--r-- | jstests/core/server9547.js | 6 | ||||
-rw-r--r-- | jstests/core/testminmax.js | 8 | ||||
-rw-r--r-- | jstests/core/wildcard_index_hint.js | 4 | ||||
-rw-r--r-- | jstests/core/wildcard_index_minmax.js | 24 |
12 files changed, 309 insertions, 283 deletions
diff --git a/jstests/core/collation.js b/jstests/core/collation.js index ba5cab6f282..c4dc36fb914 100644 --- a/jstests/core/collation.js +++ b/jstests/core/collation.js @@ -1951,20 +1951,23 @@ assert.writeOK(coll.insert({str: "D"})); // This query should fail, since there is no index to support the min/max. - assert.throws(() => coll.find() - .min({str: "b"}) - .max({str: "D"}) - .collation({locale: "en_US", strength: 2}) - .itcount()); + let err = assert.throws(() => coll.find() + .min({str: "b"}) + .max({str: "D"}) + .collation({locale: "en_US", strength: 2}) + .itcount()); + assert.commandFailedWithCode(err, 51173); // Even after building an index with the right key pattern, the query should fail since the // collations don't match. assert.commandWorked(coll.createIndex({str: 1}, {name: "noCollation"})); - assert.throws(() => coll.find() - .min({str: "b"}) - .max({str: "D"}) - .collation({locale: "en_US", strength: 2}) - .itcount()); + err = assert.throws(() => coll.find() + .min({str: "b"}) + .max({str: "D"}) + .collation({locale: "en_US", strength: 2}) + .hint({str: 1}) + .itcount()); + assert.commandFailedWithCode(err, 51174); // After building an index with the case-insensitive US English collation, the query should // work. Furthermore, the bounds defined by the min and max should respect the @@ -1976,6 +1979,7 @@ .min({str: "b"}) .max({str: "D"}) .collation({locale: "en_US", strength: 2}) + .hint("withCollation") .itcount()); // Ensure results from index with min/max query are sorted to match requested collation. diff --git a/jstests/core/explain_find.js b/jstests/core/explain_find.js index 87174e99a62..14f3f9925b2 100644 --- a/jstests/core/explain_find.js +++ b/jstests/core/explain_find.js @@ -12,13 +12,13 @@ for (var i = 0; i < 10; i++) { var explain = db.runCommand({explain: {find: collName, filter: {a: {$lte: 2}}}, verbosity: "executionStats"}); -printjson(explain); assert.commandWorked(explain); assert.eq(3, explain.executionStats.nReturned); -explain = db.runCommand( - {explain: {find: collName, min: {a: 4}, max: {a: 6}}, verbosity: "executionStats"}); -printjson(explain); +explain = db.runCommand({ + explain: {find: collName, min: {a: 4}, max: {a: 6}, hint: {a: 1}}, + verbosity: "executionStats", +}); assert.commandWorked(explain); assert.eq(2, explain.executionStats.nReturned); diff --git a/jstests/core/explain_shell_helpers.js b/jstests/core/explain_shell_helpers.js index 1aaac48ae90..f4e7496a754 100644 --- a/jstests/core/explain_shell_helpers.js +++ b/jstests/core/explain_shell_helpers.js @@ -137,18 +137,18 @@ assert.commandWorked(explain); assert(isIxscan(db, explain.queryPlanner.winningPlan)); // .min() -explain = t.explain().find().min({a: 1}).finish(); +explain = t.explain().find().min({a: 1}).hint({a: 1}).finish(); assert.commandWorked(explain); assert(isIxscan(db, explain.queryPlanner.winningPlan)); -explain = t.find().min({a: 1}).explain(); +explain = t.find().min({a: 1}).hint({a: 1}).explain(); assert.commandWorked(explain); assert(isIxscan(db, explain.queryPlanner.winningPlan)); // .max() -explain = t.explain().find().max({a: 1}).finish(); +explain = t.explain().find().max({a: 1}).hint({a: 1}).finish(); assert.commandWorked(explain); assert(isIxscan(db, explain.queryPlanner.winningPlan)); -explain = t.find().max({a: 1}).explain(); +explain = t.find().max({a: 1}).hint({a: 1}).explain(); assert.commandWorked(explain); assert(isIxscan(db, explain.queryPlanner.winningPlan)); diff --git a/jstests/core/min_max_bounds.js b/jstests/core/min_max_bounds.js index 713dc75b844..41e20157985 100644 --- a/jstests/core/min_max_bounds.js +++ b/jstests/core/min_max_bounds.js @@ -28,7 +28,7 @@ assert.eq(res[1].a, 2); assert.eq(res[2].a, 1); - res = coll.find().min({a: 1}).max({a: 3}).toArray(); + res = coll.find().min({a: 1}).max({a: 3}).hint({a: 1}).toArray(); assert.eq(res.length, 2); if (FixtureHelpers.numberOfShardsForCollection(coll) === 1) { assert.eq(res[0].a, 1); @@ -39,7 +39,7 @@ assert(resultsEq(res.map((result) => result.a), [1, 2])); } - res = coll.find().min({a: 1}).max({a: 3}).sort({a: -1}).toArray(); + res = coll.find().min({a: 1}).max({a: 3}).sort({a: -1}).hint({a: 1}).toArray(); assert.eq(res.length, 2); assert.eq(res[0].a, 2); assert.eq(res[1].a, 1); @@ -58,7 +58,7 @@ assert.eq(res[1].b, 2); assert.eq(res[2].b, 3); - res = coll.find().min({b: 3}).max({b: 1}).toArray(); + res = coll.find().min({b: 3}).max({b: 1}).hint({b: -1}).toArray(); assert.eq(res.length, 2); if (FixtureHelpers.numberOfShardsForCollection(coll) === 1) { assert.eq(res[0].b, 3); @@ -69,7 +69,7 @@ assert(resultsEq(res.map((result) => result.b), [3, 2])); } - res = coll.find().min({b: 3}).max({b: 1}).sort({b: 1}).toArray(); + res = coll.find().min({b: 3}).max({b: 1}).sort({b: 1}).hint({b: -1}).toArray(); assert.eq(res.length, 2); assert.eq(res[0].b, 2); assert.eq(res[1].b, 3); diff --git a/jstests/core/min_max_hashed_index.js b/jstests/core/min_max_hashed_index.js new file mode 100644 index 00000000000..aacd1987f44 --- /dev/null +++ b/jstests/core/min_max_hashed_index.js @@ -0,0 +1,18 @@ +/* + * Check that min() and max() work with a hashed index. + */ +(function() { + "use strict"; + + const coll = db.min_max_hashed_index; + coll.drop(); + assert.commandWorked(coll.insert({a: "test"})); + assert.commandWorked(coll.createIndex({a: 1})); + const minWithNormalIndex = coll.find({}, {_id: 0}).min({a: -Infinity}).hint({a: 1}).toArray(); + assert.eq(minWithNormalIndex, [{a: "test"}]); + + assert.commandWorked(coll.createIndex({a: "hashed"})); + const minWithHashedIndex = + coll.find({}, {_id: 0}).min({a: -Infinity}).hint({a: "hashed"}).toArray(); + assert.eq(minWithHashedIndex, [{a: "test"}]); +})(); diff --git a/jstests/core/minmax.js b/jstests/core/minmax.js index 43a321d9c80..1387d0adb4e 100644 --- a/jstests/core/minmax.js +++ b/jstests/core/minmax.js @@ -19,44 +19,69 @@ assert.commandWorked(coll.ensureIndex({a: 1, b: 1})); addData(); - assert.eq(1, coll.find().min({a: 1, b: 2}).max({a: 2, b: 1}).toArray().length); - assert.eq(2, coll.find().min({a: 1, b: 2}).max({a: 2, b: 1.5}).toArray().length); - assert.eq(2, coll.find().min({a: 1, b: 2}).max({a: 2, b: 2}).toArray().length); + assert.eq(1, + coll.find().hint({a: 1, b: 1}).min({a: 1, b: 2}).max({a: 2, b: 1}).toArray().length); + assert.eq( + 2, coll.find().hint({a: 1, b: 1}).min({a: 1, b: 2}).max({a: 2, b: 1.5}).toArray().length); + assert.eq(2, + coll.find().hint({a: 1, b: 1}).min({a: 1, b: 2}).max({a: 2, b: 2}).toArray().length); // Single bound. - assert.eq(3, coll.find().min({a: 1, b: 2}).toArray().length); - assert.eq(3, coll.find().max({a: 2, b: 1.5}).toArray().length); - assert.eq(3, coll.find().min({a: 1, b: 2}).hint({a: 1, b: 1}).toArray().length); - assert.eq(3, coll.find().max({a: 2, b: 1.5}).hint({a: 1, b: 1}).toArray().length); + assert.eq(3, coll.find().hint({a: 1, b: 1}).min({a: 1, b: 2}).toArray().length); + assert.eq(3, coll.find().hint({a: 1, b: 1}).max({a: 2, b: 1.5}).toArray().length); + assert.eq(3, + coll.find().hint({a: 1, b: 1}).min({a: 1, b: 2}).hint({a: 1, b: 1}).toArray().length); + assert.eq( + 3, coll.find().hint({a: 1, b: 1}).max({a: 2, b: 1.5}).hint({a: 1, b: 1}).toArray().length); coll.drop(); assert.commandWorked(coll.ensureIndex({a: 1, b: -1})); addData(); - assert.eq(4, coll.find().min({a: 1, b: 2}).toArray().length); - assert.eq(4, coll.find().max({a: 2, b: 0.5}).toArray().length); - assert.eq(1, coll.find().min({a: 2, b: 1}).toArray().length); - assert.eq(1, coll.find().max({a: 1, b: 1.5}).toArray().length); - assert.eq(4, coll.find().min({a: 1, b: 2}).hint({a: 1, b: -1}).toArray().length); - assert.eq(4, coll.find().max({a: 2, b: 0.5}).hint({a: 1, b: -1}).toArray().length); - assert.eq(1, coll.find().min({a: 2, b: 1}).hint({a: 1, b: -1}).toArray().length); - assert.eq(1, coll.find().max({a: 1, b: 1.5}).hint({a: 1, b: -1}).toArray().length); + assert.eq(4, coll.find().hint({a: 1, b: -1}).min({a: 1, b: 2}).toArray().length); + assert.eq(4, coll.find().hint({a: 1, b: -1}).max({a: 2, b: 0.5}).toArray().length); + assert.eq(1, coll.find().hint({a: 1, b: -1}).min({a: 2, b: 1}).toArray().length); + assert.eq(1, coll.find().hint({a: 1, b: -1}).max({a: 1, b: 1.5}).toArray().length); + assert.eq( + 4, coll.find().hint({a: 1, b: -1}).min({a: 1, b: 2}).hint({a: 1, b: -1}).toArray().length); + assert.eq( + 4, + coll.find().hint({a: 1, b: -1}).max({a: 2, b: 0.5}).hint({a: 1, b: -1}).toArray().length); + assert.eq( + 1, coll.find().hint({a: 1, b: -1}).min({a: 2, b: 1}).hint({a: 1, b: -1}).toArray().length); + assert.eq( + 1, + coll.find().hint({a: 1, b: -1}).max({a: 1, b: 1.5}).hint({a: 1, b: -1}).toArray().length); + + // Check that min/max requires a hint. + let error = assert.throws(() => coll.find().min({a: 1, b: 2}).max({a: 2, b: 1}).toArray()); + assert.eq(error.code, 51173); // Hint doesn't match. - assert.throws(function() { + error = assert.throws(function() { coll.find().min({a: 1}).hint({a: 1, b: -1}).toArray(); }); - assert.throws(function() { + assert.eq(error.code, 51174, error); + + error = assert.throws(function() { coll.find().min({a: 1, b: 1}).max({a: 1}).hint({a: 1, b: -1}).toArray(); }); - assert.throws(function() { + assert.eq(error.code, 51176, error); + + error = assert.throws(function() { coll.find().min({b: 1}).max({a: 1, b: 2}).hint({a: 1, b: -1}).toArray(); }); - assert.throws(function() { + assert.eq(error.code, 51176, error); + + // No query solutions. + error = assert.throws(function() { coll.find().min({a: 1}).hint({$natural: 1}).toArray(); }); - assert.throws(function() { + assert.eq(error.code, ErrorCodes.BadValue, error); + + error = assert.throws(function() { coll.find().max({a: 1}).hint({$natural: 1}).toArray(); }); + assert.eq(error.code, ErrorCodes.BadValue); coll.drop(); assert.commandWorked(coll.ensureIndex({a: 1})); @@ -66,50 +91,30 @@ // Reverse direction scan of the a:1 index between a:6 (inclusive) and a:3 (exclusive) is // expected to fail, as max must be > min. - let error = assert.throws(function() { - coll.find().min({a: 6}).max({a: 3}).sort({a: -1}).toArray(); - }); - assert.eq(error.code, ErrorCodes.BadValue); - error = assert.throws(function() { - coll.find().min({a: 6}).max({a: 3}).sort({a: -1}).hint({a: 1}).toArray(); + coll.find().hint({a: 1}).min({a: 6}).max({a: 3}).sort({a: -1}).toArray(); }); - assert.eq(error.code, ErrorCodes.BadValue); + assert.eq(error.code, 51175); // A find with identical min and max values is expected to fail, as max is exclusive. error = assert.throws(function() { - coll.find().min({a: 2}).max({a: 2}).toArray(); + coll.find().hint({a: 1}).min({a: 2}).max({a: 2}).toArray(); }); - assert.eq(error.code, ErrorCodes.BadValue); + assert.eq(error.code, 51175); error = assert.throws(function() { - coll.find().min({a: 2}).max({a: 2}).hint({a: 1}).toArray(); + coll.find().hint({a: 1}).min({a: 2}).max({a: 2}).sort({a: -1}).toArray(); }); - assert.eq(error.code, ErrorCodes.BadValue); - - error = assert.throws(function() { - coll.find().min({a: 2}).max({a: 2}).sort({a: -1}).toArray(); - }); - assert.eq(error.code, ErrorCodes.BadValue); - - error = assert.throws(function() { - coll.find().min({a: 2}).max({a: 2}).sort({a: -1}).hint({a: 1}).toArray(); - }); - assert.eq(error.code, ErrorCodes.BadValue); + assert.eq(error.code, 51175); coll.drop(); addData(); assert.commandWorked(coll.ensureIndex({a: 1, b: 1})); error = assert.throws(function() { - coll.find().min({a: 1, b: 2}).max({a: 1, b: 2}).toArray(); - }); - assert.eq(error.code, ErrorCodes.BadValue); - - error = assert.throws(function() { coll.find().min({a: 1, b: 2}).max({a: 1, b: 2}).hint({a: 1, b: 1}).toArray(); }); - assert.eq(error.code, ErrorCodes.BadValue); + assert.eq(error.code, 51175); // Test ascending index. coll.drop(); @@ -118,7 +123,7 @@ assert.commandWorked(coll.insert({a: 4})); assert.commandWorked(coll.insert({a: 5})); - let cursor = coll.find().min({a: 4}); + let cursor = coll.find().hint({a: 1}).min({a: 4}); if (FixtureHelpers.numberOfShardsForCollection(coll) === 1) { assert.eq(4, cursor.next().a); assert.eq(5, cursor.next().a); @@ -129,7 +134,7 @@ } assert(!cursor.hasNext()); - cursor = coll.find().max({a: 4}); + cursor = coll.find().hint({a: 1}).max({a: 4}); assert.eq(3, cursor.next()["a"]); assert(!cursor.hasNext()); @@ -137,7 +142,7 @@ assert.commandWorked(coll.dropIndexes()); assert.commandWorked(coll.ensureIndex({a: -1})); - cursor = coll.find().min({a: 4}); + cursor = coll.find().hint({a: -1}).min({a: 4}); if (FixtureHelpers.numberOfShardsForCollection(coll) === 1) { assert.eq(4, cursor.next().a); assert.eq(3, cursor.next().a); @@ -148,7 +153,7 @@ } assert(!cursor.hasNext()); - cursor = coll.find().max({a: 4}); + cursor = coll.find().hint({a: -1}).max({a: 4}); assert.eq(5, cursor.next()["a"]); assert(!cursor.hasNext()); -}());
\ No newline at end of file +}()); diff --git a/jstests/core/minmax_edge.js b/jstests/core/minmax_edge.js index 759d87dc21e..cf75edaef80 100644 --- a/jstests/core/minmax_edge.js +++ b/jstests/core/minmax_edge.js @@ -2,224 +2,231 @@ * Test that .min() and .max() queries properly handle the edge cases with NaN and Infinity. * Other edge cases are covered by C++ unit tests. */ +(function() { + const t = db.minmax_edge; + + /* + * Function to verify that the results of a query match the expected results. + * Results is the cursor toArray, expectedIds is a list of _ids + */ + function verifyResultIds(results, expectedIds) { + // check they are the same length + assert.eq(results.length, expectedIds.length); + + function compare(a, b) { + if (a._id < b._id) + return -1; + if (a._id > b._id) + return 1; + return 0; + } + + results.sort(compare); + expectedIds.sort(); + + for (var i = 0; i < results.length; i++) { + assert.eq(results._id, expectedIds._ids); + } + } -var t = db.minmax_edge; - -/* - * Function to verify that the results of a query match the expected results. - * Results is the cursor toArray, expectedIds is a list of _ids - */ -function verifyResultIds(results, expectedIds) { - // check they are the same length - assert.eq(results.length, expectedIds.length); - - function compare(a, b) { - if (a._id < b._id) - return -1; - if (a._id > b._id) - return 1; - return 0; + /* + * Shortcut to drop the collection and insert these 3 test docs. Used to change the indices + * regardless of any previous indices. + */ + function reset(t) { + t.drop(); + assert.writeOK(t.insert({_id: 0, a: 1, b: 1})); + assert.writeOK(t.insert({_id: 1, a: 1, b: 2})); + assert.writeOK(t.insert({_id: 2, a: 1, b: 3})); + + assert.writeOK(t.insert({_id: 3, a: 2, b: 1})); + assert.writeOK(t.insert({_id: 4, a: 2, b: 2})); + assert.writeOK(t.insert({_id: 5, a: 2, b: 3})); + + assert.writeOK(t.insert({_id: 6, a: 3, b: 1})); + assert.writeOK(t.insert({_id: 7, a: 3, b: 2})); + assert.writeOK(t.insert({_id: 8, a: 3, b: 3})); } - results.sort(compare); - expectedIds.sort(); + // Two helpers to save typing + function verifyMin(minDoc, idx, expectedIds) { + verifyResultIds(t.find().min(minDoc).hint(idx).toArray(), expectedIds); + } - for (var i = 0; i < results.length; i++) { - assert.eq(results._id, expectedIds._ids); + function verifyMax(minDoc, idx, expectedIds) { + verifyResultIds(t.find().max(minDoc).hint(idx).toArray(), expectedIds); } -} -/* - * Shortcut to drop the collection and insert these 3 test docs. Used to change the indices - * regardless of any previous indices. - */ -function reset(t) { - t.drop(); - assert.writeOK(t.insert({_id: 0, a: 1, b: 1})); - assert.writeOK(t.insert({_id: 1, a: 1, b: 2})); - assert.writeOK(t.insert({_id: 2, a: 1, b: 3})); + // Basic ascending index. + reset(t); + let indexSpec = {a: 1}; + assert.commandWorked(t.createIndex(indexSpec)); + + verifyMin({a: Infinity}, indexSpec, []); + verifyMax({a: Infinity}, indexSpec, [0, 1, 2, 3, 4, 5, 6, 7, 8]); - assert.writeOK(t.insert({_id: 3, a: 2, b: 1})); - assert.writeOK(t.insert({_id: 4, a: 2, b: 2})); - assert.writeOK(t.insert({_id: 5, a: 2, b: 3})); + verifyMin({a: -Infinity}, indexSpec, [0, 1, 2, 3, 4, 5, 6, 7, 8]); + verifyMax({a: -Infinity}, indexSpec, []); - assert.writeOK(t.insert({_id: 6, a: 3, b: 1})); - assert.writeOK(t.insert({_id: 7, a: 3, b: 2})); - assert.writeOK(t.insert({_id: 8, a: 3, b: 3})); -} + // NaN < all ints. + verifyMin({a: NaN}, indexSpec, [0, 1, 2, 3, 4, 5, 6, 7, 8]); + verifyMax({a: NaN}, indexSpec, []); -// Two helpers to save typing -function verifyMin(minDoc, expectedIds) { - verifyResultIds(t.find().min(minDoc).toArray(), expectedIds); -} + // {a: 1} > all ints. + verifyMin({a: {a: 1}}, indexSpec, []); + verifyMax({a: {a: 1}}, indexSpec, [0, 1, 2, 3, 4, 5, 6, 7, 8]); -function verifyMax(minDoc, expectedIds) { - verifyResultIds(t.find().max(minDoc).toArray(), expectedIds); -} + // 'a' > all ints. + verifyMin({a: 'a'}, indexSpec, []); + verifyMax({a: 'a'}, indexSpec, [0, 1, 2, 3, 4, 5, 6, 7, 8]); -// Basic ascending index. -reset(t); -assert.commandWorked(t.ensureIndex({a: 1})); + // Now with a compound index. + reset(t); + indexSpec = {a: 1, b: -1}; -verifyMin({a: Infinity}, []); -verifyMax({a: Infinity}, [0, 1, 2, 3, 4, 5, 6, 7, 8]); + assert.commandWorked(t.createIndex(indexSpec)); -verifyMin({a: -Infinity}, [0, 1, 2, 3, 4, 5, 6, 7, 8]); -verifyMax({a: -Infinity}, []); + // Same as single-key index assertions, with b field present. + verifyMin({a: NaN, b: 1}, indexSpec, [0, 1, 2, 3, 4, 5, 6, 7, 8]); + verifyMax({a: NaN, b: 1}, indexSpec, []); -// NaN < all ints. -verifyMin({a: NaN}, [0, 1, 2, 3, 4, 5, 6, 7, 8]); -verifyMax({a: NaN}, []); + verifyMin({a: Infinity, b: 1}, indexSpec, []); + verifyMax({a: Infinity, b: 1}, indexSpec, [0, 1, 2, 3, 4, 5, 6, 7, 8]); -// {a: 1} > all ints. -verifyMin({a: {a: 1}}, []); -verifyMax({a: {a: 1}}, [0, 1, 2, 3, 4, 5, 6, 7, 8]); + verifyMin({a: -Infinity, b: 1}, indexSpec, [0, 1, 2, 3, 4, 5, 6, 7, 8]); + verifyMax({a: -Infinity, b: 1}, indexSpec, []); -// 'a' > all ints. -verifyMin({a: 'a'}, []); -verifyMax({a: 'a'}, [0, 1, 2, 3, 4, 5, 6, 7, 8]); + verifyMin({a: {a: 1}, b: 1}, indexSpec, []); + verifyMax({a: {a: 1}, b: 1}, indexSpec, [0, 1, 2, 3, 4, 5, 6, 7, 8]); -// Now with a compound index. -reset(t); -assert.commandWorked(t.ensureIndex({a: 1, b: -1})); + verifyMin({a: 'a', b: 1}, indexSpec, []); + verifyMax({a: 'a', b: 1}, indexSpec, [0, 1, 2, 3, 4, 5, 6, 7, 8]); -// Same as single-key index assertions, with b field present. -verifyMin({a: NaN, b: 1}, [0, 1, 2, 3, 4, 5, 6, 7, 8]); -verifyMax({a: NaN, b: 1}, []); + // Edge cases on b values + verifyMin({a: 1, b: Infinity}, indexSpec, [0, 1, 2, 3, 4, 5, 6, 7, 8]); + verifyMin({a: 2, b: Infinity}, indexSpec, [3, 4, 5, 6, 7, 8]); + verifyMin({a: 3, b: Infinity}, indexSpec, [6, 7, 8]); + verifyMax({a: 1, b: Infinity}, indexSpec, []); + verifyMax({a: 2, b: Infinity}, indexSpec, [0, 1, 2]); + verifyMax({a: 3, b: Infinity}, indexSpec, [0, 1, 2, 3, 4, 5]); -verifyMin({a: Infinity, b: 1}, []); -verifyMax({a: Infinity, b: 1}, [0, 1, 2, 3, 4, 5, 6, 7, 8]); + verifyMin({a: 1, b: -Infinity}, indexSpec, [3, 4, 5, 6, 7, 8]); + verifyMin({a: 2, b: -Infinity}, indexSpec, [6, 7, 8]); + verifyMin({a: 3, b: -Infinity}, indexSpec, []); + verifyMax({a: 1, b: -Infinity}, indexSpec, [0, 1, 2]); + verifyMax({a: 2, b: -Infinity}, indexSpec, [0, 1, 2, 3, 4, 5]); + verifyMax({a: 3, b: -Infinity}, indexSpec, [0, 1, 2, 3, 4, 5, 6, 7, 8]); -verifyMin({a: -Infinity, b: 1}, [0, 1, 2, 3, 4, 5, 6, 7, 8]); -verifyMax({a: -Infinity, b: 1}, []); + verifyMin({a: 2, b: NaN}, indexSpec, [6, 7, 8]); + verifyMax({a: 2, b: NaN}, indexSpec, [0, 1, 2, 3, 4, 5]); -verifyMin({a: {a: 1}, b: 1}, []); -verifyMax({a: {a: 1}, b: 1}, [0, 1, 2, 3, 4, 5, 6, 7, 8]); - -verifyMin({a: 'a', b: 1}, []); -verifyMax({a: 'a', b: 1}, [0, 1, 2, 3, 4, 5, 6, 7, 8]); - -// Edge cases on b values -verifyMin({a: 1, b: Infinity}, [0, 1, 2, 3, 4, 5, 6, 7, 8]); -verifyMin({a: 2, b: Infinity}, [3, 4, 5, 6, 7, 8]); -verifyMin({a: 3, b: Infinity}, [6, 7, 8]); -verifyMax({a: 1, b: Infinity}, []); -verifyMax({a: 2, b: Infinity}, [0, 1, 2]); -verifyMax({a: 3, b: Infinity}, [0, 1, 2, 3, 4, 5]); - -verifyMin({a: 1, b: -Infinity}, [3, 4, 5, 6, 7, 8]); -verifyMin({a: 2, b: -Infinity}, [6, 7, 8]); -verifyMin({a: 3, b: -Infinity}, []); -verifyMax({a: 1, b: -Infinity}, [0, 1, 2]); -verifyMax({a: 2, b: -Infinity}, [0, 1, 2, 3, 4, 5]); -verifyMax({a: 3, b: -Infinity}, [0, 1, 2, 3, 4, 5, 6, 7, 8]); + verifyMin({a: 2, b: {b: 1}}, indexSpec, [3, 4, 5, 6, 7, 8]); + verifyMax({a: 2, b: {b: 1}}, indexSpec, [0, 1, 2]); -verifyMin({a: 2, b: NaN}, [6, 7, 8]); -verifyMax({a: 2, b: NaN}, [0, 1, 2, 3, 4, 5]); - -verifyMin({a: 2, b: {b: 1}}, [3, 4, 5, 6, 7, 8]); -verifyMax({a: 2, b: {b: 1}}, [0, 1, 2]); - -verifyMin({a: 2, b: 'b'}, [3, 4, 5, 6, 7, 8]); -verifyMax({a: 2, b: 'b'}, [0, 1, 2]); - -// Test descending index. -reset(t); -t.ensureIndex({a: -1}); - -verifyMin({a: NaN}, []); -verifyMax({a: NaN}, [0, 1, 2, 3, 4, 5, 6, 7, 8]); - -verifyMin({a: Infinity}, [0, 1, 2, 3, 4, 5, 6, 7, 8]); -verifyMax({a: Infinity}, []); - -verifyMin({a: -Infinity}, []); -verifyMax({a: -Infinity}, [0, 1, 2, 3, 4, 5, 6, 7, 8]); - -verifyMin({a: {a: 1}}, [0, 1, 2, 3, 4, 5, 6, 7, 8]); -verifyMax({a: {a: 1}}, []); + verifyMin({a: 2, b: 'b'}, indexSpec, [3, 4, 5, 6, 7, 8]); + verifyMax({a: 2, b: 'b'}, indexSpec, [0, 1, 2]); -verifyMin({a: 'a'}, [0, 1, 2, 3, 4, 5, 6, 7, 8]); -verifyMax({a: 'a'}, []); + // Test descending index. + reset(t); + indexSpec = {a: -1}; + assert.commandWorked(t.createIndex(indexSpec)); -// Now with a compound index. -reset(t); -t.ensureIndex({a: -1, b: -1}); + verifyMin({a: NaN}, indexSpec, []); + verifyMax({a: NaN}, indexSpec, [0, 1, 2, 3, 4, 5, 6, 7, 8]); -// Same as single-key index assertions, with b field present. -verifyMin({a: NaN, b: 1}, []); -verifyMax({a: NaN, b: 1}, [0, 1, 2, 3, 4, 5, 6, 7, 8]); + verifyMin({a: Infinity}, indexSpec, [0, 1, 2, 3, 4, 5, 6, 7, 8]); + verifyMax({a: Infinity}, indexSpec, []); -verifyMin({a: Infinity, b: 1}, [0, 1, 2, 3, 4, 5, 6, 7, 8]); -verifyMax({a: Infinity, b: 1}, []); + verifyMin({a: -Infinity}, indexSpec, []); + verifyMax({a: -Infinity}, indexSpec, [0, 1, 2, 3, 4, 5, 6, 7, 8]); -verifyMin({a: -Infinity, b: 1}, []); -verifyMax({a: -Infinity, b: 1}, [0, 1, 2, 3, 4, 5, 6, 7, 8]); + verifyMin({a: {a: 1}}, indexSpec, [0, 1, 2, 3, 4, 5, 6, 7, 8]); + verifyMax({a: {a: 1}}, indexSpec, []); -verifyMin({a: {a: 1}, b: 1}, [0, 1, 2, 3, 4, 5, 6, 7, 8]); -verifyMax({a: {a: 1}, b: 1}, []); + verifyMin({a: 'a'}, indexSpec, [0, 1, 2, 3, 4, 5, 6, 7, 8]); + verifyMax({a: 'a'}, indexSpec, []); -verifyMin({a: 'a', b: 1}, [0, 1, 2, 3, 4, 5, 6, 7, 8]); -verifyMax({a: 'a', b: 1}, []); + // Now with a compound index. + reset(t); + indexSpec = {a: -1, b: -1}; + assert.commandWorked(t.createIndex(indexSpec)); -// Edge cases on b values. -verifyMin({a: 1, b: Infinity}, [0, 1, 2]); -verifyMin({a: 2, b: Infinity}, [0, 1, 2, 3, 4, 5]); -verifyMin({a: 3, b: Infinity}, [0, 1, 2, 3, 4, 5, 6, 7, 8]); -verifyMax({a: 1, b: Infinity}, [3, 4, 5, 6, 7, 8]); -verifyMax({a: 2, b: Infinity}, [6, 7, 8]); -verifyMax({a: 3, b: Infinity}, []); + // Same as single-key index assertions, with b field present. + verifyMin({a: NaN, b: 1}, indexSpec, []); + verifyMax({a: NaN, b: 1}, indexSpec, [0, 1, 2, 3, 4, 5, 6, 7, 8]); -verifyMin({a: 1, b: -Infinity}, []); -verifyMin({a: 2, b: -Infinity}, [0, 1, 2]); -verifyMin({a: 3, b: -Infinity}, [0, 1, 2, 3, 4, 5]); -verifyMax({a: 1, b: -Infinity}, [0, 1, 2, 3, 4, 5, 6, 7, 8]); -verifyMax({a: 2, b: -Infinity}, [3, 4, 5, 6, 7, 8]); -verifyMax({a: 3, b: -Infinity}, [6, 7, 8]); + verifyMin({a: Infinity, b: 1}, indexSpec, [0, 1, 2, 3, 4, 5, 6, 7, 8]); + verifyMax({a: Infinity, b: 1}, indexSpec, []); -verifyMin({a: 2, b: NaN}, [0, 1, 2]); -verifyMax({a: 2, b: NaN}, [3, 4, 5, 6, 7, 8]); - -verifyMin({a: 2, b: {b: 1}}, [3, 4, 5, 6, 7, 8]); -verifyMax({a: 2, b: {b: 1}}, [0, 1, 2]); + verifyMin({a: -Infinity, b: 1}, indexSpec, []); + verifyMax({a: -Infinity, b: 1}, indexSpec, [0, 1, 2, 3, 4, 5, 6, 7, 8]); -verifyMin({a: 2, b: 'b'}, [3, 4, 5, 6, 7, 8]); -verifyMax({a: 2, b: 'b'}, [0, 1, 2]); + verifyMin({a: {a: 1}, b: 1}, indexSpec, [0, 1, 2, 3, 4, 5, 6, 7, 8]); + verifyMax({a: {a: 1}, b: 1}, indexSpec, []); -// Now a couple cases with an extra compound index. -t.drop(); -t.ensureIndex({a: 1, b: -1, c: 1}); -// The following documents are in order according to the index. -t.insert({_id: 0, a: 1, b: 'b', c: 1}); -t.insert({_id: 1, a: 1, b: 'b', c: 2}); -t.insert({_id: 2, a: 1, b: 'a', c: 1}); -t.insert({_id: 3, a: 1, b: 'a', c: 2}); -t.insert({_id: 4, a: 2, b: 'b', c: 1}); -t.insert({_id: 5, a: 2, b: 'b', c: 2}); -t.insert({_id: 6, a: 2, b: 'a', c: 1}); -t.insert({_id: 7, a: 2, b: 'a', c: 2}); - -verifyMin({a: 1, b: 'a', c: 1}, [2, 3, 4, 5, 6, 7]); -verifyMin({a: 2, b: 'a', c: 2}, [7]); -verifyMax({a: 1, b: 'a', c: 1}, [0, 1]); -verifyMax({a: 2, b: 'a', c: 2}, [0, 1, 2, 3, 4, 5, 6]); - -verifyMin({a: Infinity, b: 'a', c: 2}, []); -verifyMax({a: Infinity, b: 'a', c: 2}, [0, 1, 2, 3, 4, 5, 6, 7]); + verifyMin({a: 'a', b: 1}, indexSpec, [0, 1, 2, 3, 4, 5, 6, 7, 8]); + verifyMax({a: 'a', b: 1}, indexSpec, []); -verifyMin({a: -Infinity, b: 'a', c: 2}, [0, 1, 2, 3, 4, 5, 6, 7]); -verifyMax({a: -Infinity, b: 'a', c: 2}, []); + // Edge cases on b values. + verifyMin({a: 1, b: Infinity}, indexSpec, [0, 1, 2]); + verifyMin({a: 2, b: Infinity}, indexSpec, [0, 1, 2, 3, 4, 5]); + verifyMin({a: 3, b: Infinity}, indexSpec, [0, 1, 2, 3, 4, 5, 6, 7, 8]); + verifyMax({a: 1, b: Infinity}, indexSpec, [3, 4, 5, 6, 7, 8]); + verifyMax({a: 2, b: Infinity}, indexSpec, [6, 7, 8]); + verifyMax({a: 3, b: Infinity}, indexSpec, []); -// 'a' > Infinity, actually. -verifyMin({a: 1, b: Infinity, c: 2}, [4, 5, 6, 7]); -verifyMax({a: 1, b: Infinity, c: 2}, [0, 1, 2, 3]); + verifyMin({a: 1, b: -Infinity}, indexSpec, []); + verifyMin({a: 2, b: -Infinity}, indexSpec, [0, 1, 2]); + verifyMin({a: 3, b: -Infinity}, indexSpec, [0, 1, 2, 3, 4, 5]); + verifyMax({a: 1, b: -Infinity}, indexSpec, [0, 1, 2, 3, 4, 5, 6, 7, 8]); + verifyMax({a: 2, b: -Infinity}, indexSpec, [3, 4, 5, 6, 7, 8]); + verifyMax({a: 3, b: -Infinity}, indexSpec, [6, 7, 8]); -// Also, 'a' > -Infinity. -verifyMin({a: 1, b: -Infinity, c: 2}, [4, 5, 6, 7]); -verifyMax({a: 1, b: -Infinity, c: 2}, [0, 1, 2, 3]); + verifyMin({a: 2, b: NaN}, indexSpec, [0, 1, 2]); + verifyMax({a: 2, b: NaN}, indexSpec, [3, 4, 5, 6, 7, 8]); -verifyMin({a: 1, b: 'a', c: Infinity}, [4, 5, 6, 7]); -verifyMax({a: 1, b: 'a', c: Infinity}, [0, 1, 2, 3]); + verifyMin({a: 2, b: {b: 1}}, indexSpec, [3, 4, 5, 6, 7, 8]); + verifyMax({a: 2, b: {b: 1}}, indexSpec, [0, 1, 2]); -verifyMin({a: 1, b: 'a', c: -Infinity}, [2, 3, 4, 5, 6, 7]); -verifyMax({a: 1, b: 'a', c: -Infinity}, [0, 1]); + verifyMin({a: 2, b: 'b'}, indexSpec, [3, 4, 5, 6, 7, 8]); + verifyMax({a: 2, b: 'b'}, indexSpec, [0, 1, 2]); + + // Now a couple cases with an extra compound index. + t.drop(); + indexSpec = {a: 1, b: -1, c: 1}; + assert.commandWorked(t.createIndex(indexSpec)); + // The following documents are in order according to the index. + t.insert({_id: 0, a: 1, b: 'b', c: 1}); + t.insert({_id: 1, a: 1, b: 'b', c: 2}); + t.insert({_id: 2, a: 1, b: 'a', c: 1}); + t.insert({_id: 3, a: 1, b: 'a', c: 2}); + t.insert({_id: 4, a: 2, b: 'b', c: 1}); + t.insert({_id: 5, a: 2, b: 'b', c: 2}); + t.insert({_id: 6, a: 2, b: 'a', c: 1}); + t.insert({_id: 7, a: 2, b: 'a', c: 2}); + + verifyMin({a: 1, b: 'a', c: 1}, indexSpec, [2, 3, 4, 5, 6, 7]); + verifyMin({a: 2, b: 'a', c: 2}, indexSpec, [7]); + verifyMax({a: 1, b: 'a', c: 1}, indexSpec, [0, 1]); + verifyMax({a: 2, b: 'a', c: 2}, indexSpec, [0, 1, 2, 3, 4, 5, 6]); + + verifyMin({a: Infinity, b: 'a', c: 2}, indexSpec, []); + verifyMax({a: Infinity, b: 'a', c: 2}, indexSpec, [0, 1, 2, 3, 4, 5, 6, 7]); + + verifyMin({a: -Infinity, b: 'a', c: 2}, indexSpec, [0, 1, 2, 3, 4, 5, 6, 7]); + verifyMax({a: -Infinity, b: 'a', c: 2}, indexSpec, []); + + // 'a' > Infinity, actually. + verifyMin({a: 1, b: Infinity, c: 2}, indexSpec, [4, 5, 6, 7]); + verifyMax({a: 1, b: Infinity, c: 2}, indexSpec, [0, 1, 2, 3]); + + // Also, 'a' > -Infinity. + verifyMin({a: 1, b: -Infinity, c: 2}, indexSpec, [4, 5, 6, 7]); + verifyMax({a: 1, b: -Infinity, c: 2}, indexSpec, [0, 1, 2, 3]); + + verifyMin({a: 1, b: 'a', c: Infinity}, indexSpec, [4, 5, 6, 7]); + verifyMax({a: 1, b: 'a', c: Infinity}, indexSpec, [0, 1, 2, 3]); + + verifyMin({a: 1, b: 'a', c: -Infinity}, indexSpec, [2, 3, 4, 5, 6, 7]); + verifyMax({a: 1, b: 'a', c: -Infinity}, indexSpec, [0, 1]); +})(); diff --git a/jstests/core/profile_find.js b/jstests/core/profile_find.js index 6c89781bd33..cfdf1c995ec 100644 --- a/jstests/core/profile_find.js +++ b/jstests/core/profile_find.js @@ -146,11 +146,11 @@ profileObj = getLatestProfilerEntry(testDB, profileEntryFilter); assert.eq(profileObj.command.maxTimeMS, maxTimeMS, tojson(profileObj)); - assert.eq(coll.find().max({_id: 3}).itcount(), 1); + assert.eq(coll.find().max({_id: 3}).hint({_id: 1}).itcount(), 1); profileObj = getLatestProfilerEntry(testDB, profileEntryFilter); assert.eq(profileObj.command.max, {_id: 3}, tojson(profileObj)); - assert.eq(coll.find().min({_id: 0}).itcount(), 1); + assert.eq(coll.find().min({_id: 0}).hint({_id: 1}).itcount(), 1); profileObj = getLatestProfilerEntry(testDB, profileEntryFilter); assert.eq(profileObj.command.min, {_id: 0}, tojson(profileObj)); diff --git a/jstests/core/server9547.js b/jstests/core/server9547.js index 56f059d82b3..66b17644e15 100644 --- a/jstests/core/server9547.js +++ b/jstests/core/server9547.js @@ -11,10 +11,10 @@ for (var i = 0; i < 10; i++) { t.ensureIndex({a: 1}); // note: max() value is exclusive upper bound -assert.eq(4, t.find({}).max({a: 4}).toArray().length, "no order"); +assert.eq(4, t.find({}).max({a: 4}).hint({a: 1}).toArray().length, "no order"); // Ascending order is fine. -assert.eq(4, t.find({}).max({a: 4}).sort({a: 1}).toArray().length, "ascending"); +assert.eq(4, t.find({}).max({a: 4}).sort({a: 1}).hint({a: 1}).toArray().length, "ascending"); // Descending order is fine. -assert.eq(4, t.find({}).max({a: 4}).sort({a: -1}).toArray().length, "descending"); +assert.eq(4, t.find({}).max({a: 4}).sort({a: -1}).hint({a: 1}).toArray().length, "descending"); diff --git a/jstests/core/testminmax.js b/jstests/core/testminmax.js index ea60191f3a9..3ebf0a13f3a 100644 --- a/jstests/core/testminmax.js +++ b/jstests/core/testminmax.js @@ -23,11 +23,5 @@ t.insert({ printjson(t.find() .min({"_id": "IBM.N|00000000000000000000"}) .max({"_id": "IBM.N|99999999999999999999"}) + .hint({_id: 1}) .toArray()); - -// this should be 2!! add assertion when fixed -// http://jira.mongodb.org/browse/SERVER-675 -print(t.find() - .min({"_id": "IBM.N|00000000000000000000"}) - .max({"_id": "IBM.N|99999999999999999999"}) - .count()); diff --git a/jstests/core/wildcard_index_hint.js b/jstests/core/wildcard_index_hint.js index 64fc61880d4..3f1ac41b42f 100644 --- a/jstests/core/wildcard_index_hint.js +++ b/jstests/core/wildcard_index_hint.js @@ -93,7 +93,7 @@ // Min/max with $** index hint. assert.commandFailedWithCode( db.runCommand({find: coll.getName(), filter: {"b": 1}, min: {"a": 1}, hint: {"$**": 1}}), - ErrorCodes.BadValue); + 51174); // Hint a $** index on a query with compound fields. assertExpectedIndexAnswersQueryWithHint( @@ -102,4 +102,4 @@ // Hint a $** index by name. assertExpectedIndexAnswersQueryWithHint( {"a": 1}, "$**_1", "$**_1", [{a: 1, b: 1, c: {d: 1, e: 1}}, {a: 1, b: 2, c: {d: 2, e: 2}}]); -})();
\ No newline at end of file +})(); diff --git a/jstests/core/wildcard_index_minmax.js b/jstests/core/wildcard_index_minmax.js index 14fbbaea42e..b13d2c81b94 100644 --- a/jstests/core/wildcard_index_minmax.js +++ b/jstests/core/wildcard_index_minmax.js @@ -21,28 +21,26 @@ // Throws error for $** index min. assert.commandFailedWithCode( - db.runCommand({find: coll.getName(), min: {"a": 0.5}, hint: {"$**": 1}}), - ErrorCodes.BadValue); + db.runCommand({find: coll.getName(), min: {"a": 0.5}, hint: {"$**": 1}}), 51174); // Throws error for $** index max. assert.commandFailedWithCode( - db.runCommand({find: coll.getName(), max: {"a": 1.5}, hint: {"$**": 1}}), - ErrorCodes.BadValue); + db.runCommand({find: coll.getName(), max: {"a": 1.5}, hint: {"$**": 1}}), 51174); // Throws error for $** index min/max. assert.commandFailedWithCode( db.runCommand({find: coll.getName(), min: {"a": 0.5}, max: {"a": 1.5}, hint: {"$**": 1}}), - ErrorCodes.BadValue); + 51174); // Throws error for $** index min with filter of a different value. assert.commandFailedWithCode( db.runCommand({find: coll.getName(), filter: {"a": 2}, min: {"a": 1}, hint: {"$**": 1}}), - ErrorCodes.BadValue); + 51174); // Throws error for $** index max with filter of a different value. assert.commandFailedWithCode( db.runCommand({find: coll.getName(), filter: {"a": 1}, max: {"a": 1.5}, hint: {"$**": 1}}), - ErrorCodes.BadValue); + 51174); // Throws error for $** index min and max with filter of a different value. assert.commandFailedWithCode(db.runCommand({ @@ -52,17 +50,17 @@ max: {"a": 1.5}, hint: {"$**": 1} }), - ErrorCodes.BadValue); + 51174); // Throws error for $** index min with filter of the same value. assert.commandFailedWithCode( db.runCommand({find: coll.getName(), filter: {"a": 1}, min: {"a": 1}, hint: {"$**": 1}}), - ErrorCodes.BadValue); + 51174); // Throws error for $** index max with filter of the same value. assert.commandFailedWithCode( db.runCommand({find: coll.getName(), filter: {"a": 1}, max: {"a": 1}, hint: {"$**": 1}}), - ErrorCodes.BadValue); + 51174); // Throws error for $** index min and max with filter of the same value. assert.commandFailedWithCode(db.runCommand({ @@ -72,9 +70,9 @@ max: {"a": 1}, hint: {"$**": 1} }), - ErrorCodes.BadValue); + 51174); // $** index does not interfere with valid min/max. - assertArrayEq(coll.find({}, {_id: 0}).min({"a": 0.5}).max({"a": 1.5}).toArray(), + assertArrayEq(coll.find({}, {_id: 0}).min({"a": 0.5}).max({"a": 1.5}).hint({a: 1}).toArray(), [{a: 1, b: 1}, {a: 1, b: 2}]); -})();
\ No newline at end of file +})(); |