Files
mongo/jstests/core/find_and_modify_server6865.js
Charlie 7a36b1598c SERVER-16063 Rewrite the findAndModify command.
Changed UpdateStage to return the prior or newly-updated version of
a document if request. also changed DeleteStage to return the deleted
document if requested.

Added explain support to the findAndModify command.
2015-04-14 10:27:18 -04:00

354 lines
11 KiB
JavaScript

/**
* Test that projection with a positional operator works with findAndModify
* when remove=true or new=false, but not when new=true.
*/
(function() {
'use strict';
var collName = 'find_and_modify_server6865';
var t = db.getCollection(collName);
t.drop();
/**
* Asserts that the specified query and projection returns the expected
* result, using both the find() operation and the findAndModify command.
*
* insert -- document to insert after dropping collection t
* cmdObj -- arguments to the findAndModify command
*
* expected -- the document 'value' expected to be returned after the
* projection is applied
*/
function testFAMWorked(insert, cmdObj, expected) {
t.drop();
t.insert(insert);
var res;
if (!cmdObj['new']) {
// Test that the find operation returns the expected result.
res = t.findOne(cmdObj['query'], cmdObj['fields']);
assert.eq(res, expected, 'positional projection failed for find');
}
// Test that the findAndModify command returns the expected result.
res = t.runCommand('findAndModify', cmdObj);
assert.commandWorked(res, 'findAndModify command failed');
assert.eq(res.value, expected, 'positional projection failed for findAndModify');
if (cmdObj['new']) {
// Test that the find operation returns the expected result.
res = t.findOne(cmdObj['query'], cmdObj['fields']);
assert.eq(res, expected, 'positional projection failed for find');
}
}
/**
* Asserts that the specified findAndModify command returns an error.
*/
function testFAMFailed(insert, cmdObj) {
t.drop();
t.insert(insert);
var res = t.runCommand('findAndModify', cmdObj);
assert.commandFailed(res, 'findAndModify command unexpectedly succeeded');
}
//
// Delete operations
//
// Simple query that uses an inclusion projection.
testFAMWorked(
{_id: 42, a: [1, 2], b: 3},
{query: {_id: 42}, fields: {_id: 0, b: 1}, remove: true},
{b: 3}
);
// Simple query that uses an exclusion projection.
testFAMWorked(
{_id: 42, a: [1, 2], b: 3, c: 4},
{query: {_id: 42}, fields: {a: 0, b: 0}, remove: true},
{_id: 42, c: 4}
);
// Simple query that uses $elemMatch in the projection.
testFAMWorked(
{_id: 42, b: [{name: 'first', value: 1},
{name: 'second', value: 2},
{name: 'third', value: 3}]
},
{query: {_id: 42}, fields: {b: {$elemMatch: {value: 2}}}, remove: true},
{_id: 42, b: [{name: 'second', value: 2}]}
);
// Query on an array of values while using a positional projection.
testFAMWorked(
{_id: 42, a: [1, 2]},
{query: {a: 2}, fields: {'a.$': 1}, remove: true},
{_id: 42, a: [2]}
);
// Query on an array of objects while using a positional projection.
testFAMWorked(
{_id: 42, b: [{name: 'first', value: 1},
{name: 'second', value: 2},
{name: 'third', value: 3}]
},
{query: {_id: 42, 'b.name': 'third'}, fields: {'b.$': 1}, remove: true},
{_id: 42, b: [{name: 'third', value: 3}]}
);
// Query on an array of objects while using a position projection.
// Verifies that the projection {'b.$.value': 1} is treated the
// same as {'b.$': 1}.
testFAMWorked(
{_id: 42, b: [{name: 'first', value: 1},
{name: 'second', value: 2},
{name: 'third', value: 3}]
},
{query: {_id: 42, 'b.name': 'third'}, fields: {'b.$.value': 1}, remove: true},
{_id: 42, b: [{name: 'third', value: 3}]}
);
// Query on an array of objects using $elemMatch while using an inclusion projection.
testFAMWorked(
{_id: 42, a: 5, b: [{name: 'john', value: 1},
{name: 'jess', value: 2},
{name: 'jeff', value: 3}]
},
{
query: {b: {$elemMatch: {name: 'john', value: {$lt: 2}}}},
fields: {_id: 0, a: 5},
remove: true
},
{a: 5}
);
// Query on an array of objects using $elemMatch while using the positional
// operator in the projection.
testFAMWorked(
{_id: 42, b: [{name: 'john', value: 1},
{name: 'jess', value: 2},
{name: 'jeff', value: 3}]
},
{
query: {b: {$elemMatch: {name: 'john', value: {$lt: 2}}}},
fields: {_id: 0, 'b.$': 1},
remove: true
},
{b: [{name: 'john', value: 1}]}
);
//
// Update operations with new=false
//
// Simple query that uses an inclusion projection.
testFAMWorked(
{_id: 42, a: [1, 2], b: 3},
{query: {_id: 42}, fields: {_id: 0, b: 1}, update: {$inc: {b: 1}}, new: false},
{b: 3}
);
// Simple query that uses an exclusion projection.
testFAMWorked(
{_id: 42, a: [1, 2], b: 3, c: 4},
{query: {_id: 42}, fields: {a: 0, b: 0}, update: {$set: {c: 5}}, new: false},
{_id: 42, c: 4}
);
// Simple query that uses $elemMatch in the projection.
testFAMWorked(
{_id: 42, b: [{name: 'first', value: 1},
{name: 'second', value: 2},
{name: 'third', value: 3}]
},
{
query: {_id: 42},
fields: {b: {$elemMatch: {value: 2}}},
update: {$set: {name: '2nd'}},
new: false
},
{_id: 42, b: [{name: 'second', value: 2}]}
);
// Query on an array of values while using a positional projection.
testFAMWorked(
{_id: 42, a: [1, 2]},
{query: {a: 2}, fields: {'a.$': 1}, update: {$set: {'b.kind': 'xyz'}}, new: false},
{_id: 42, a: [2]}
);
// Query on an array of objects while using a positional projection.
testFAMWorked(
{_id: 42, b: [{name: 'first', value: 1},
{name: 'second', value: 2},
{name: 'third', value: 3}]
},
{
query: {_id: 42, 'b.name': 'third'},
fields: {'b.$': 1},
update: {$set: {'b.$.kind': 'xyz'}},
new: false
},
{_id: 42, b: [{name: 'third', value: 3}]}
);
// Query on an array of objects while using $elemMatch in the projection,
// where the matched array element is modified.
testFAMWorked(
{_id: 1, a: [{x: 1, y: 1}, {x: 1, y: 2}]},
{
query: {_id: 1},
fields: {a: {$elemMatch: {x: 1}}},
update: {$pop: {a: -1}},
new: false
},
{_id: 1, a: [{x: 1, y: 1}]}
);
// Query on an array of objects using $elemMatch while using an inclusion projection.
testFAMWorked(
{_id: 42, a: 5, b: [{name: 'john', value: 1},
{name: 'jess', value: 2},
{name: 'jeff', value: 3}]
},
{
query: {b: {$elemMatch: {name: 'john', value: {$lt: 2}}}},
fields: {_id: 0, a: 5},
update: {$inc: {a: 6}},
new: false
},
{a: 5}
);
// Query on an array of objects using $elemMatch while using the positional
// operator in the projection.
testFAMWorked(
{_id: 42, b: [{name: 'john', value: 1},
{name: 'jess', value: 2},
{name: 'jeff', value: 3}]
},
{
query: {b: {$elemMatch: {name: 'john', value: {$lt: 2}}}},
fields: {_id: 0, 'b.$': 1},
update: {$set: {name: 'james'}},
new: false
},
{b: [{name: 'john', value: 1}]}
);
//
// Update operations with new=true
//
// Simple query that uses an inclusion projection.
testFAMWorked(
{_id: 42, a: [1, 2], b: 3},
{query: {_id: 42}, fields: {_id: 0, b: 1}, update: {$inc: {b: 1}}, new: true},
{b: 4}
);
// Simple query that uses an exclusion projection.
testFAMWorked(
{_id: 42, a: [1, 2], b: 3, c: 4},
{query: {_id: 42}, fields: {a: 0, b: 0}, update: {$set: {c: 5}}, new: true},
{_id: 42, c: 5}
);
// Simple query that uses $elemMatch in the projection.
testFAMWorked(
{_id: 42, b: [{name: 'first', value: 1},
{name: 'second', value: 2},
{name: 'third', value: 3}]
},
{
query: {_id: 42},
fields: {b: {$elemMatch: {value: 2}}},
update: {$set: {'b.1.name': '2nd'}},
new: true
},
{_id: 42, b: [{name: '2nd', value: 2}]}
);
// Query on an array of values while using a positional projection.
testFAMFailed(
{_id: 42, a: [1, 2]},
{query: {a: 2}, fields: {'a.$': 1}, update: {$set: {'b.kind': 'xyz'}}, new: true}
);
// Query on an array of objects while using a positional projection.
testFAMFailed(
{_id: 42, b: [{name: 'first', value: 1},
{name: 'second', value: 2},
{name: 'third', value: 3}]
},
{
query: {_id: 42, 'b.name': 'third'},
fields: {'b.$': 1},
update: {$set: {'b.$.kind': 'xyz'}},
new: true
}
);
// Query on an array of objects while using $elemMatch in the projection.
testFAMWorked(
{_id: 42, b: [{name: 'first', value: 1},
{name: 'second', value: 2},
{name: 'third', value: 3}]
},
{
query: {_id: 42},
fields: {b: {$elemMatch: {value: 2}}, c: 1},
update: {$set: {c: 'xyz'}},
new: true
},
{_id: 42, b: [{name: 'second', value: 2}], c: 'xyz'}
);
// Query on an array of objects while using $elemMatch in the projection,
// where the matched array element is modified.
testFAMWorked(
{_id: 1, a: [{x: 1, y: 1}, {x: 1, y: 2}]},
{
query: {_id: 1},
fields: {a: {$elemMatch: {x: 1}}},
update: {$pop: {a: -1}},
new: true
},
{_id: 1, a: [{x: 1, y: 2}]}
);
// Query on an array of objects using $elemMatch while using an inclusion projection.
testFAMWorked(
{_id: 42, a: 5, b: [{name: 'john', value: 1},
{name: 'jess', value: 2},
{name: 'jeff', value: 3}]
},
{
query: {b: {$elemMatch: {name: 'john', value: {$lt: 2}}}},
fields: {_id: 0, a: 5},
update: {$inc: {a: 6}},
new: true
},
{a: 11}
);
// Query on an array of objects using $elemMatch while using the positional
// operator in the projection.
testFAMFailed(
{_id: 42, b: [{name: 'john', value: 1},
{name: 'jess', value: 2},
{name: 'jeff', value: 3}]
},
{
query: {b: {$elemMatch: {name: 'john', value: {$lt: 2}}}},
fields: {_id: 0, 'b.$': 1},
update: {$set: {name: 'james'}},
new: true
}
);
})();