diff options
author | Ian Boros <puppyofkosh@gmail.com> | 2019-02-22 19:17:37 -0500 |
---|---|---|
committer | Ian Boros <puppyofkosh@gmail.com> | 2019-02-22 19:19:33 -0500 |
commit | 4253bddd476f19fb6af295323acc9d5af15da598 (patch) | |
tree | 59208de80aa28fee01956af649c6fc34ff1d3864 /jstests/core | |
parent | be68e9b78da63075c9b82304ea27ae4725fe894c (diff) | |
download | mongo-4253bddd476f19fb6af295323acc9d5af15da598.tar.gz |
SERVER-39470 Modernize arrayfind8.js
Diffstat (limited to 'jstests/core')
-rw-r--r-- | jstests/core/arrayfind8.js | 281 |
1 files changed, 133 insertions, 148 deletions
diff --git a/jstests/core/arrayfind8.js b/jstests/core/arrayfind8.js index a687351b554..f9693182a7a 100644 --- a/jstests/core/arrayfind8.js +++ b/jstests/core/arrayfind8.js @@ -1,163 +1,148 @@ -// Matching behavior for $elemMatch applied to a top level element. -// SERVER-1264 -// SERVER-4180 -var debuggingEnabled = false; - -t = db.jstests_arrayfind8; -t.drop(); - -function debug(x) { - if (debuggingEnabled) { - printjson(x); +/** + * Matching behavior for $elemMatch applied to a top level element. + * Includes tests for bugs described in SERVER-1264 and SERVER-4180. + */ +(function() { + "use strict"; + + const coll = db.jstests_arrayfind8; + coll.drop(); + + // May be changed during the test. + let currentIndexSpec = {a: 1}; + + /** + * Check that the query results match the documents in the 'expected' array. + */ + function assertResults(expected, query, context) { + assert.eq(expected.length, coll.count(query), 'unexpected count in ' + context); + const results = coll.find(query).toArray(); + const resultsAOnly = results.map((r) => r.a); + assert.sameMembers(resultsAOnly, expected); } -} - -/** Set index state for the test. */ -function setIndexKey(key) { - indexKey = key; - indexSpec = {}; - indexSpec[key] = 1; -} - -setIndexKey('a'); - -/** Check that the query results match the documents in the 'expected' array. */ -function assertResults(expected, query, context) { - debug(query); - assert.eq(expected.length, t.count(query), 'unexpected count in ' + context); - results = t.find(query).toArray(); - for (i in results) { - found = false; - for (j in expected) { - if (friendlyEqual(expected[j], results[i].a)) { - found = true; + + /** + * Check matching for different query types. + * @param bothMatch - document matched by both standardQuery and elemMatchQuery + * @param elemMatch - document matched by elemMatchQuery but not standardQuery + * @param notElemMatch - document matched by standardQuery but not elemMatchQuery + */ + function checkMatch( + bothMatch, elemMatch, nonElemMatch, standardQuery, elemMatchQuery, context) { + function mayPush(arr, elt) { + if (elt) { + arr.push(elt); } } - assert(found, 'unexpected result ' + results[i] + ' in ' + context); + + let expectedStandardQueryResults = []; + mayPush(expectedStandardQueryResults, bothMatch); + mayPush(expectedStandardQueryResults, nonElemMatch); + assertResults(expectedStandardQueryResults, standardQuery, context + ' standard query'); + + let expectedElemMatchQueryResults = []; + mayPush(expectedElemMatchQueryResults, bothMatch); + mayPush(expectedElemMatchQueryResults, elemMatch); + assertResults(expectedElemMatchQueryResults, elemMatchQuery, context + ' elemMatch query'); } -} -/** - * Check matching for different query types. - * @param bothMatch - document matched by both standardQuery and elemMatchQuery - * @param elemMatch - document matched by elemMatchQuery but not standardQuery - * @param notElemMatch - document matched by standardQuery but not elemMatchQuery - */ -function checkMatch(bothMatch, elemMatch, nonElemMatch, standardQuery, elemMatchQuery, context) { - function mayPush(arr, elt) { - if (elt) { - arr.push(elt); + /** + * Check matching and for different query types. + * @param subQuery - part of a query, to be provided as is for a standard query and within a + * $elemMatch clause for a $elemMatch query + * @param bothMatch - document matched by both standardQuery and elemMatchQuery + * @param elemMatch - document matched by elemMatchQuery but not standardQuery + * @param notElemMatch - document matched by standardQuery but not elemMatchQuery + * @param additionalConstraints - additional query parameters not generated from @param subQuery + */ + function checkQuery(subQuery, bothMatch, elemMatch, nonElemMatch, additionalConstraints) { + coll.drop(); + additionalConstraints = additionalConstraints || {}; + + // Construct standard and elemMatch queries from subQuery. + const firstSubQueryKey = Object.keySet(subQuery)[0]; + let standardQuery = null; + if (firstSubQueryKey[0] == '$') { + standardQuery = {$and: [{a: subQuery}, additionalConstraints]}; + } else { + // If the subQuery contains a field rather than operators, append to the 'a' field. + let modifiedSubQuery = {}; + modifiedSubQuery['a.' + firstSubQueryKey] = subQuery[firstSubQueryKey]; + standardQuery = {$and: [modifiedSubQuery, additionalConstraints]}; } - } + const elemMatchQuery = {$and: [{a: {$elemMatch: subQuery}}, additionalConstraints]}; - expectedStandardQueryResults = []; - mayPush(expectedStandardQueryResults, bothMatch); - mayPush(expectedStandardQueryResults, nonElemMatch); - assertResults(expectedStandardQueryResults, standardQuery, context + ' standard query'); + function insertValueIfNotNull(val) { + if (val) { + assert.commandWorked(coll.insert({a: val})); + } + } - expectedElemMatchQueryResults = []; - mayPush(expectedElemMatchQueryResults, bothMatch); - mayPush(expectedElemMatchQueryResults, elemMatch); - assertResults(expectedElemMatchQueryResults, elemMatchQuery, context + ' elemMatch query'); -} + // Save all documents and check matching without indexes. + insertValueIfNotNull(bothMatch); + insertValueIfNotNull(elemMatch); + insertValueIfNotNull(nonElemMatch); -/** - * Check matching and for different query types. - * @param subQuery - part of a query, to be provided as is for a standard query and within a - * $elemMatch clause for a $elemMatch query - * @param bothMatch - document matched by both standardQuery and elemMatchQuery - * @param elemMatch - document matched by elemMatchQuery but not standardQuery - * @param notElemMatch - document matched by standardQuery but not elemMatchQuery - * @param additionalConstraints - additional query parameters not generated from @param subQuery - */ -function checkQuery(subQuery, bothMatch, elemMatch, nonElemMatch, additionalConstraints) { - t.drop(); - additionalConstraints = additionalConstraints || {}; - - // Construct standard and elemMatch queries from subQuery. - firstSubQueryKey = Object.keySet(subQuery)[0]; - if (firstSubQueryKey[0] == '$') { - standardQuery = {$and: [{a: subQuery}, additionalConstraints]}; - } else { - // If the subQuery contains a field rather than operators, append to the 'a' field. - modifiedSubQuery = {}; - modifiedSubQuery['a.' + firstSubQueryKey] = subQuery[firstSubQueryKey]; - standardQuery = {$and: [modifiedSubQuery, additionalConstraints]}; - } - elemMatchQuery = {$and: [{a: {$elemMatch: subQuery}}, additionalConstraints]}; - debug(elemMatchQuery); + checkMatch(bothMatch, elemMatch, nonElemMatch, standardQuery, elemMatchQuery, 'unindexed'); - function maySave(aValue) { - if (aValue) { - debug({a: aValue}); - t.save({a: aValue}); - } + // Check matching and index bounds for a single key index. + + assert.eq(coll.drop(), true); + insertValueIfNotNull(bothMatch); + insertValueIfNotNull(elemMatch); + // The nonElemMatch document is not tested here, as it will often make the index multikey. + assert.commandWorked(coll.createIndex(currentIndexSpec)); + checkMatch(bothMatch, elemMatch, null, standardQuery, elemMatchQuery, 'single key index'); + + // Check matching and index bounds for a multikey index. + + // Now the nonElemMatch document is tested. + insertValueIfNotNull(nonElemMatch); + // Force the index to be multikey. + assert.commandWorked(coll.insert({a: [-1, -2]})); + assert.commandWorked(coll.insert({a: {b: [-1, -2]}})); + checkMatch( + bothMatch, elemMatch, nonElemMatch, standardQuery, elemMatchQuery, 'multikey index'); } - // Save all documents and check matching without indexes. - maySave(bothMatch); - maySave(elemMatch); - maySave(nonElemMatch); - - checkMatch(bothMatch, elemMatch, nonElemMatch, standardQuery, elemMatchQuery, 'unindexed'); - - // Check matching and index bounds for a single key index. - - t.drop(); - maySave(bothMatch); - maySave(elemMatch); - // The nonElemMatch document is not tested here, as it will often make the index multikey. - t.ensureIndex(indexSpec); - checkMatch(bothMatch, elemMatch, null, standardQuery, elemMatchQuery, 'single key index'); - - // Check matching and index bounds for a multikey index. - - // Now the nonElemMatch document is tested. - maySave(nonElemMatch); - // Force the index to be multikey. - t.save({a: [-1, -2]}); - t.save({a: {b: [-1, -2]}}); - checkMatch(bothMatch, elemMatch, nonElemMatch, standardQuery, elemMatchQuery, 'multikey index'); -} - -maxNumber = Infinity; - -// Basic test. -checkQuery({$gt: 4}, [5]); - -// Multiple constraints within a $elemMatch clause. -checkQuery({$gt: 4, $lt: 6}, [5], null, [3, 7]); -checkQuery({$gt: 4, $not: {$gte: 6}}, [5]); -checkQuery({$gt: 4, $not: {$ne: 6}}, [6]); -checkQuery({$gte: 5, $lte: 5}, [5], null, [4, 6]); -checkQuery({$in: [4, 6], $gt: 5}, [6], null, [4, 7]); -checkQuery({$regex: '^a'}, ['a']); - -// Some constraints within a $elemMatch clause and other constraints outside of it. -checkQuery({$gt: 4}, [5], null, null, {a: {$lt: 6}}); -checkQuery({$gte: 5}, [5], null, null, {a: {$lte: 5}}); -checkQuery({$in: [4, 6]}, [6], null, null, {a: {$gt: 5}}); - -// Constraints in different $elemMatch clauses. -checkQuery({$gt: 4}, [5], null, null, {a: {$elemMatch: {$lt: 6}}}); -checkQuery({$gt: 4}, [3, 7], null, null, {a: {$elemMatch: {$lt: 6}}}); -checkQuery({$gte: 5}, [5], null, null, {a: {$elemMatch: {$lte: 5}}}); -checkQuery({$in: [4, 6]}, [6], null, null, {a: {$elemMatch: {$gt: 5}}}); - -// TODO SERVER-1264 -if (0) { - checkQuery({$elemMatch: {$in: [5]}}, null, [[5]], [5], null); -} + // Basic test. + checkQuery({$gt: 4}, [5]); + + // Multiple constraints within a $elemMatch clause. + checkQuery({$gt: 4, $lt: 6}, [5], null, [3, 7]); + checkQuery({$gt: 4, $not: {$gte: 6}}, [5]); + checkQuery({$gt: 4, $not: {$ne: 6}}, [6]); + checkQuery({$gte: 5, $lte: 5}, [5], null, [4, 6]); + checkQuery({$in: [4, 6], $gt: 5}, [6], null, [4, 7]); + checkQuery({$regex: '^a'}, ['a']); -setIndexKey('a.b'); -checkQuery({$elemMatch: {b: {$gte: 1, $lte: 1}}}, null, [[{b: 1}]], [{b: 1}], null); -checkQuery({$elemMatch: {b: {$gte: 1, $lte: 1}}}, null, [[{b: [0, 2]}]], [{b: [0, 2]}], null); + // Some constraints within a $elemMatch clause and other constraints outside of it. + checkQuery({$gt: 4}, [5], null, null, {a: {$lt: 6}}); + checkQuery({$gte: 5}, [5], null, null, {a: {$lte: 5}}); + checkQuery({$in: [4, 6]}, [6], null, null, {a: {$gt: 5}}); -// Constraints for a top level (SERVER-1264 style) $elemMatch nested within a non top level -// $elemMatch. -checkQuery({b: {$elemMatch: {$gte: 1, $lte: 1}}}, [{b: [1]}]); -checkQuery({b: {$elemMatch: {$gte: 1, $lte: 4}}}, [{b: [1]}]); + // Constraints in different $elemMatch clauses. + checkQuery({$gt: 4}, [5], null, null, {a: {$elemMatch: {$lt: 6}}}); + checkQuery({$gt: 4}, [3, 7], null, null, {a: {$elemMatch: {$lt: 6}}}); + checkQuery({$gte: 5}, [5], null, null, {a: {$elemMatch: {$lte: 5}}}); + checkQuery({$in: [4, 6]}, [6], null, null, {a: {$elemMatch: {$gt: 5}}}); + + checkQuery({$elemMatch: {$in: [5]}}, null, [[5]], [5], null); -checkQuery({b: {$elemMatch: {$gte: 1, $lte: 4}}}, [{b: [2]}], null, null, {'a.b': {$in: [2, 5]}}); -checkQuery( - {b: {$elemMatch: {$in: [1, 2]}, $in: [2, 3]}}, [{b: [2]}], null, [{b: [1]}, {b: [3]}], null); + currentIndexSpec = {"a.b": 1}; + checkQuery({$elemMatch: {b: {$gte: 1, $lte: 1}}}, null, [[{b: 1}]], [{b: 1}], null); + checkQuery({$elemMatch: {b: {$gte: 1, $lte: 1}}}, null, [[{b: [0, 2]}]], [{b: [0, 2]}], null); + + // Constraints for a top level (SERVER-1264 style) $elemMatch nested within a non top level + // $elemMatch. + checkQuery({b: {$elemMatch: {$gte: 1, $lte: 1}}}, [{b: [1]}]); + checkQuery({b: {$elemMatch: {$gte: 1, $lte: 4}}}, [{b: [1]}]); + + checkQuery( + {b: {$elemMatch: {$gte: 1, $lte: 4}}}, [{b: [2]}], null, null, {'a.b': {$in: [2, 5]}}); + checkQuery({b: {$elemMatch: {$in: [1, 2]}, $in: [2, 3]}}, + [{b: [2]}], + null, + [{b: [1]}, {b: [3]}], + null); +})(); |