171 lines
6.1 KiB
JavaScript
171 lines
6.1 KiB
JavaScript
// Check $match pipeline stage.
|
|
// - Filtering behavior equivalent to a mongo query.
|
|
// - $where and geo operators are not allowed
|
|
(function() {
|
|
"use strict";
|
|
|
|
load('jstests/aggregation/extras/utils.js');
|
|
|
|
const coll = db.jstests_aggregation_match;
|
|
coll.drop();
|
|
|
|
const identityProjection = {
|
|
_id: '$_id',
|
|
a: '$a'
|
|
};
|
|
|
|
/** Assert that an aggregation generated the expected error. */
|
|
function assertError(expectedCode, matchSpec) {
|
|
const matchStage = {$match: matchSpec};
|
|
// Check where matching is folded in to DocumentSourceCursor.
|
|
assertErrorCode(coll, [matchStage], expectedCode);
|
|
// Check where matching is not folded in to DocumentSourceCursor.
|
|
assertErrorCode(coll, [{$project: identityProjection}, matchStage], expectedCode);
|
|
}
|
|
|
|
/** Assert that the contents of two arrays are equal, ignoring element ordering. */
|
|
function assertEqualResultsUnordered(one, two) {
|
|
let oneStr = one.map(function(x) {
|
|
return tojson(x);
|
|
});
|
|
let twoStr = two.map(function(x) {
|
|
return tojson(x);
|
|
});
|
|
oneStr.sort();
|
|
twoStr.sort();
|
|
assert.eq(oneStr, twoStr);
|
|
}
|
|
|
|
/** Assert that an aggregation result is as expected. */
|
|
function assertResults(expectedResults, matchSpec) {
|
|
const findResults = coll.find(matchSpec).toArray();
|
|
if (expectedResults) {
|
|
assertEqualResultsUnordered(expectedResults, findResults);
|
|
}
|
|
const matchStage = {$match: matchSpec};
|
|
// Check where matching is folded in to DocumentSourceCursor.
|
|
assertEqualResultsUnordered(findResults, coll.aggregate(matchStage).toArray());
|
|
// Check where matching is not folded in to DocumentSourceCursor.
|
|
assertEqualResultsUnordered(
|
|
findResults, coll.aggregate({$project: identityProjection}, matchStage).toArray());
|
|
}
|
|
|
|
// Invalid matcher syntax.
|
|
assertError(2, {a: {$mod: [0 /* invalid */, 0]}});
|
|
|
|
// $where not allowed.
|
|
assertError(ErrorCodes.BadValue, {$where: 'true'});
|
|
|
|
// Geo not allowed.
|
|
assertError(ErrorCodes.BadValue, {$match: {a: {$near: [0, 0]}}});
|
|
|
|
function checkMatchResults(indexed) {
|
|
// No results.
|
|
coll.remove({});
|
|
assertResults([], {});
|
|
|
|
assert.commandWorked(coll.insert({_id: 0, a: 1}));
|
|
assert.commandWorked(coll.insert({_id: 1, a: 2}));
|
|
assert.commandWorked(coll.insert({_id: 2, a: 3}));
|
|
|
|
// Empty query.
|
|
assertResults([{_id: 0, a: 1}, {_id: 1, a: 2}, {_id: 2, a: 3}], {});
|
|
|
|
// Simple queries.
|
|
assertResults([{_id: 0, a: 1}], {a: 1});
|
|
assertResults([{_id: 1, a: 2}], {a: 2});
|
|
assertResults([{_id: 1, a: 2}, {_id: 2, a: 3}], {a: {$gt: 1}});
|
|
assertResults([{_id: 0, a: 1}, {_id: 1, a: 2}], {a: {$lte: 2}});
|
|
assertResults([{_id: 0, a: 1}, {_id: 2, a: 3}], {a: {$in: [1, 3]}});
|
|
|
|
// Regular expression.
|
|
coll.remove({});
|
|
assert.commandWorked(coll.insert({_id: 0, a: 'x'}));
|
|
assert.commandWorked(coll.insert({_id: 1, a: 'yx'}));
|
|
assertResults([{_id: 0, a: 'x'}], {a: /^x/});
|
|
assertResults([{_id: 0, a: 'x'}, {_id: 1, a: 'yx'}], {a: /x/});
|
|
|
|
// Dotted field.
|
|
coll.remove({});
|
|
assert.commandWorked(coll.insert({_id: 0, a: {b: 4}}));
|
|
assert.commandWorked(coll.insert({_id: 1, a: 2}));
|
|
assertResults([{_id: 0, a: {b: 4}}], {'a.b': 4});
|
|
|
|
// Value within an array.
|
|
coll.remove({});
|
|
assert.commandWorked(coll.insert({_id: 0, a: [1, 2, 3]}));
|
|
assert.commandWorked(coll.insert({_id: 1, a: [2, 2, 3]}));
|
|
assert.commandWorked(coll.insert({_id: 2, a: [2, 2, 2]}));
|
|
assertResults([{_id: 0, a: [1, 2, 3]}, {_id: 1, a: [2, 2, 3]}], {a: 3});
|
|
|
|
// Missing, null, $exists matching.
|
|
coll.remove({});
|
|
assert.commandWorked(coll.insert({_id: 0}));
|
|
assert.commandWorked(coll.insert({_id: 1, a: null}));
|
|
assert.commandWorked(coll.insert({_id: 3, a: 0}));
|
|
assertResults([{_id: 0}, {_id: 1, a: null}], {a: null});
|
|
assertResults(null, {a: {$exists: true}});
|
|
assertResults(null, {a: {$exists: false}});
|
|
|
|
// $elemMatch
|
|
coll.remove({});
|
|
assert.commandWorked(coll.insert({_id: 0, a: [1, 2]}));
|
|
assert.commandWorked(coll.insert({_id: 1, a: [1, 2, 3]}));
|
|
assertResults([{_id: 1, a: [1, 2, 3]}], {a: {$elemMatch: {$gt: 1, $mod: [2, 1]}}});
|
|
|
|
coll.remove({});
|
|
assert.commandWorked(coll.insert({_id: 0, a: [{b: 1}, {c: 2}]}));
|
|
assert.commandWorked(coll.insert({_id: 1, a: [{b: 1, c: 2}]}));
|
|
assertResults([{_id: 1, a: [{b: 1, c: 2}]}], {a: {$elemMatch: {b: 1, c: 2}}});
|
|
|
|
// $size
|
|
coll.remove({});
|
|
assert.commandWorked(coll.insert({}));
|
|
assert.commandWorked(coll.insert({a: null}));
|
|
assert.commandWorked(coll.insert({a: []}));
|
|
assert.commandWorked(coll.insert({a: [1]}));
|
|
assert.commandWorked(coll.insert({a: [1, 2]}));
|
|
assertResults(null, {a: {$size: 0}});
|
|
assertResults(null, {a: {$size: 1}});
|
|
assertResults(null, {a: {$size: 2}});
|
|
|
|
// $type
|
|
coll.remove({});
|
|
assert.commandWorked(coll.insert({}));
|
|
assert.commandWorked(coll.insert({a: null}));
|
|
assert.commandWorked(coll.insert({a: NumberInt(1)}));
|
|
assert.commandWorked(coll.insert({a: NumberLong(2)}));
|
|
assert.commandWorked(coll.insert({a: 66.6}));
|
|
assert.commandWorked(coll.insert({a: 'abc'}));
|
|
assert.commandWorked(coll.insert({a: /xyz/}));
|
|
assert.commandWorked(coll.insert({a: {q: 1}}));
|
|
assert.commandWorked(coll.insert({a: true}));
|
|
assert.commandWorked(coll.insert({a: new Date()}));
|
|
assert.commandWorked(coll.insert({a: new ObjectId()}));
|
|
for (let type = 1; type <= 18; ++type) {
|
|
assertResults(null, {a: {$type: type}});
|
|
}
|
|
|
|
coll.remove({});
|
|
assert.commandWorked(coll.insert({_id: 0, a: 1}));
|
|
assert.commandWorked(coll.insert({_id: 1, a: 2}));
|
|
assert.commandWorked(coll.insert({_id: 2, a: 3}));
|
|
|
|
// $and
|
|
assertResults([{_id: 1, a: 2}], {$and: [{a: 2}, {_id: 1}]});
|
|
assertResults([], {$and: [{a: 1}, {_id: 1}]});
|
|
assertResults([{_id: 1, a: 2}, {_id: 2, a: 3}],
|
|
{$and: [{$or: [{_id: 1}, {a: 3}]}, {$or: [{_id: 2}, {a: 2}]}]});
|
|
|
|
// $or
|
|
assertResults([{_id: 0, a: 1}, {_id: 2, a: 3}], {$or: [{_id: 0}, {a: 3}]});
|
|
}
|
|
|
|
checkMatchResults(false);
|
|
coll.createIndex({a: 1});
|
|
checkMatchResults(true);
|
|
coll.createIndex({'a.b': 1});
|
|
coll.createIndex({'a.c': 1});
|
|
checkMatchResults(true);
|
|
})();
|