1173 lines
32 KiB
JavaScript
1173 lines
32 KiB
JavaScript
// This test has assertions that expect a certain document is deleted whereas updateOnes,
|
|
// deleteOnes, and findAndModify without shard key can pick and modify any matching document.
|
|
//
|
|
// @tags: [
|
|
// assumes_unsharded_collection,
|
|
// assumes_write_concern_unchanged,
|
|
// requires_fastcount,
|
|
// requires_getmore,
|
|
// # Unacknowledged writes are prohibited with sessions:
|
|
// does_not_support_retryable_writes,
|
|
// # Time series collections do not support `sort` in `findAndModify` commands.
|
|
// exclude_from_timeseries_crud_passthrough,
|
|
// ]
|
|
|
|
import {arrayEq} from "jstests/aggregation/extras/utils.js";
|
|
|
|
let crudAPISpecTests = function crudAPISpecTests() {
|
|
// Get the colllection
|
|
let coll = db.crud_tests;
|
|
|
|
// Setup
|
|
function createTestExecutor(coll, method, verifyResult) {
|
|
return function (args) {
|
|
// Drop collection
|
|
coll.drop();
|
|
// Insert test data
|
|
let r = coll.insertMany(args.insert);
|
|
assert.eq(args.insert.length, r.insertedIds.length);
|
|
|
|
// Execute the method with arguments
|
|
r = coll[method].apply(coll, args.params);
|
|
verifyResult(args.result, r);
|
|
|
|
// Get all the results
|
|
assert.soonNoExcept(
|
|
function () {
|
|
let results = coll.find({}).sort({_id: 1}).toArray();
|
|
assert.docEq(args.expected, results);
|
|
return true;
|
|
},
|
|
function () {
|
|
return "collection never contained expected documents";
|
|
},
|
|
);
|
|
};
|
|
}
|
|
|
|
function checkResultObject(expected, actual) {
|
|
// Only assert on the "modifiedCount" property
|
|
assert.docEq(expected, actual);
|
|
}
|
|
|
|
// Setup executors
|
|
let deleteManyExecutor = createTestExecutor(coll, "deleteMany", checkResultObject);
|
|
let deleteOneExecutor = createTestExecutor(coll, "deleteOne", checkResultObject);
|
|
let bulkWriteExecutor = createTestExecutor(coll, "bulkWrite", checkResultObject);
|
|
let findOneAndDeleteExecutor = createTestExecutor(coll, "findOneAndDelete", checkResultObject);
|
|
let findOneAndReplaceExecutor = createTestExecutor(coll, "findOneAndReplace", checkResultObject);
|
|
let findOneAndUpdateExecutor = createTestExecutor(coll, "findOneAndUpdate", checkResultObject);
|
|
let insertManyExecutor = createTestExecutor(coll, "insertMany", checkResultObject);
|
|
let insertOneExecutor = createTestExecutor(coll, "insertOne", checkResultObject);
|
|
let replaceOneExecutor = createTestExecutor(coll, "replaceOne", checkResultObject);
|
|
let updateManyExecutor = createTestExecutor(coll, "updateMany", checkResultObject);
|
|
let updateOneExecutor = createTestExecutor(coll, "updateOne", checkResultObject);
|
|
let countExecutor = createTestExecutor(coll, "count", assert.eq);
|
|
let distinctExecutor = createTestExecutor(coll, "distinct", (a, b) => assert(arrayEq(a, b)));
|
|
|
|
//
|
|
// BulkWrite
|
|
//
|
|
|
|
bulkWriteExecutor({
|
|
insert: [
|
|
{_id: 1, c: 1},
|
|
{_id: 2, c: 2},
|
|
{_id: 3, c: 3},
|
|
],
|
|
params: [
|
|
[
|
|
{insertOne: {document: {_id: 4, a: 1}}},
|
|
{updateOne: {filter: {_id: 5, a: 2}, update: {$set: {a: 2}}, upsert: true}},
|
|
{updateMany: {filter: {_id: 6, a: 3}, update: {$set: {a: 3}}, upsert: true}},
|
|
{deleteOne: {filter: {c: 1}}},
|
|
{insertOne: {document: {_id: 7, c: 2}}},
|
|
{deleteMany: {filter: {c: 2}}},
|
|
{replaceOne: {filter: {c: 3}, replacement: {c: 4}, upsert: true}},
|
|
],
|
|
],
|
|
result: {
|
|
acknowledged: true,
|
|
insertedCount: 2,
|
|
matchedCount: 1,
|
|
deletedCount: 3,
|
|
upsertedCount: 2,
|
|
insertedIds: {"0": 4, "4": 7},
|
|
upsertedIds: {"1": 5, "2": 6},
|
|
},
|
|
expected: [
|
|
{"_id": 3, "c": 4},
|
|
{"_id": 4, "a": 1},
|
|
{"_id": 5, "a": 2},
|
|
{"_id": 6, "a": 3},
|
|
],
|
|
});
|
|
|
|
bulkWriteExecutor({
|
|
insert: [
|
|
{_id: 1, c: 1},
|
|
{_id: 2, c: 2},
|
|
{_id: 3, c: 3},
|
|
],
|
|
params: [
|
|
[
|
|
{insertOne: {document: {_id: 4, a: 1}}},
|
|
{updateOne: {filter: {_id: 5, a: 2}, update: {$set: {a: 2}}, upsert: true}},
|
|
{updateMany: {filter: {_id: 6, a: 3}, update: {$set: {a: 3}}, upsert: true}},
|
|
{deleteOne: {filter: {c: 1}}},
|
|
{deleteMany: {filter: {c: 2}}},
|
|
{replaceOne: {filter: {c: 3}, replacement: {c: 4}, upsert: true}},
|
|
],
|
|
{ordered: false},
|
|
],
|
|
result: {
|
|
acknowledged: true,
|
|
insertedCount: 1,
|
|
matchedCount: 1,
|
|
deletedCount: 2,
|
|
upsertedCount: 2,
|
|
insertedIds: {"0": 4},
|
|
upsertedIds: {"1": 5, "2": 6},
|
|
},
|
|
expected: [
|
|
{"_id": 3, "c": 4},
|
|
{"_id": 4, "a": 1},
|
|
{"_id": 5, "a": 2},
|
|
{"_id": 6, "a": 3},
|
|
],
|
|
});
|
|
|
|
// DeleteMany
|
|
//
|
|
|
|
// DeleteMany when many documents match
|
|
deleteManyExecutor({
|
|
insert: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
params: [{_id: {$gt: 1}}],
|
|
result: {acknowledged: true, deletedCount: 2},
|
|
expected: [{_id: 1, x: 11}],
|
|
});
|
|
// DeleteMany when no document matches
|
|
deleteManyExecutor({
|
|
insert: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
params: [{_id: 4}],
|
|
result: {acknowledged: true, deletedCount: 0},
|
|
expected: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
});
|
|
// DeleteMany when many documents match, no write concern
|
|
deleteManyExecutor({
|
|
insert: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
params: [{_id: {$gt: 1}}, {w: 0}],
|
|
result: {acknowledged: false},
|
|
expected: [{_id: 1, x: 11}],
|
|
});
|
|
|
|
//
|
|
// DeleteOne
|
|
//
|
|
|
|
// DeleteOne when many documents match
|
|
deleteOneExecutor({
|
|
insert: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
params: [{_id: {$gt: 1}}],
|
|
result: {acknowledged: true, deletedCount: 1},
|
|
expected: [
|
|
{_id: 1, x: 11},
|
|
{_id: 3, x: 33},
|
|
],
|
|
});
|
|
// DeleteOne when one document matches
|
|
deleteOneExecutor({
|
|
insert: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
params: [{_id: 2}],
|
|
result: {acknowledged: true, deletedCount: 1},
|
|
expected: [
|
|
{_id: 1, x: 11},
|
|
{_id: 3, x: 33},
|
|
],
|
|
});
|
|
// DeleteOne when no documents match
|
|
deleteOneExecutor({
|
|
insert: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
params: [{_id: 4}],
|
|
result: {acknowledged: true, deletedCount: 0},
|
|
expected: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
});
|
|
// DeleteOne when many documents match, no write concern
|
|
deleteOneExecutor({
|
|
insert: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
params: [{_id: {$gt: 1}}, {w: 0}],
|
|
result: {acknowledged: false},
|
|
expected: [
|
|
{_id: 1, x: 11},
|
|
{_id: 3, x: 33},
|
|
],
|
|
});
|
|
|
|
//
|
|
// FindOneAndDelete
|
|
//
|
|
|
|
// FindOneAndDelete when one document matches
|
|
findOneAndDeleteExecutor({
|
|
insert: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
params: [{_id: {$gt: 2}}, {projection: {x: 1, _id: 0}, sort: {x: 1}}],
|
|
result: {x: 33},
|
|
expected: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
],
|
|
});
|
|
// FindOneAndDelete when one document matches
|
|
findOneAndDeleteExecutor({
|
|
insert: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
params: [{_id: 2}, {projection: {x: 1, _id: 0}, sort: {x: 1}}],
|
|
result: {x: 22},
|
|
expected: [
|
|
{_id: 1, x: 11},
|
|
{_id: 3, x: 33},
|
|
],
|
|
});
|
|
// FindOneAndDelete when no documents match
|
|
findOneAndDeleteExecutor({
|
|
insert: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
params: [{_id: 4}, {projection: {x: 1, _id: 0}, sort: {x: 1}}],
|
|
result: null,
|
|
expected: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
});
|
|
|
|
//
|
|
// FindOneAndReplace
|
|
//
|
|
|
|
// FindOneAndReplace when many documents match returning the document before modification
|
|
findOneAndReplaceExecutor({
|
|
insert: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
params: [{_id: {$gt: 1}}, {x: 32}, {projection: {x: 1, _id: 0}, sort: {x: 1}}],
|
|
result: {x: 22},
|
|
expected: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 32},
|
|
{_id: 3, x: 33},
|
|
],
|
|
});
|
|
// FindOneAndReplace when many documents match returning the document after modification
|
|
findOneAndReplaceExecutor({
|
|
insert: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
params: [{_id: {$gt: 1}}, {x: 32}, {projection: {x: 1, _id: 0}, sort: {x: 1}, returnNewDocument: true}],
|
|
result: {x: 32},
|
|
expected: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 32},
|
|
{_id: 3, x: 33},
|
|
],
|
|
});
|
|
// FindOneAndReplace when one document matches returning the document before modification
|
|
findOneAndReplaceExecutor({
|
|
insert: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
params: [{_id: 2}, {x: 32}, {projection: {x: 1, _id: 0}, sort: {x: 1}}],
|
|
result: {x: 22},
|
|
expected: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 32},
|
|
{_id: 3, x: 33},
|
|
],
|
|
});
|
|
// FindOneAndReplace when one document matches returning the document after modification
|
|
findOneAndReplaceExecutor({
|
|
insert: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
params: [{_id: 2}, {x: 32}, {projection: {x: 1, _id: 0}, sort: {x: 1}, returnNewDocument: true}],
|
|
result: {x: 32},
|
|
expected: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 32},
|
|
{_id: 3, x: 33},
|
|
],
|
|
});
|
|
// FindOneAndReplace when no documents match returning the document before modification
|
|
findOneAndReplaceExecutor({
|
|
insert: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
params: [{_id: 4}, {x: 44}, {projection: {x: 1, _id: 0}, sort: {x: 1}}],
|
|
result: null,
|
|
expected: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
});
|
|
// FindOneAndReplace when no documents match with upsert returning the document before
|
|
// modification
|
|
findOneAndReplaceExecutor({
|
|
insert: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
params: [{_id: 4}, {x: 44}, {projection: {x: 1, _id: 0}, sort: {x: 1}, upsert: true}],
|
|
result: null,
|
|
expected: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
{_id: 4, x: 44},
|
|
],
|
|
});
|
|
// FindOneAndReplace when no documents match returning the document after modification
|
|
findOneAndReplaceExecutor({
|
|
insert: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
params: [{_id: 4}, {x: 44}, {projection: {x: 1, _id: 0}, sort: {x: 1}, returnNewDocument: true}],
|
|
result: null,
|
|
expected: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
});
|
|
// FindOneAndReplace when no documents match with upsert returning the document after
|
|
// modification
|
|
findOneAndReplaceExecutor({
|
|
insert: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
params: [{_id: 4}, {x: 44}, {projection: {x: 1, _id: 0}, sort: {x: 1}, returnNewDocument: true, upsert: true}],
|
|
result: {x: 44},
|
|
expected: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
{_id: 4, x: 44},
|
|
],
|
|
});
|
|
|
|
assert.throws(function () {
|
|
coll.findOneAndReplace({a: 1}, {$set: {b: 1}});
|
|
});
|
|
|
|
//
|
|
// FindOneAndUpdate
|
|
//
|
|
|
|
// FindOneAndUpdate when many documents match returning the document before modification
|
|
findOneAndUpdateExecutor({
|
|
insert: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
params: [{_id: {$gt: 1}}, {$inc: {x: 1}}, {projection: {x: 1, _id: 0}, sort: {x: 1}}],
|
|
result: {x: 22},
|
|
expected: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 23},
|
|
{_id: 3, x: 33},
|
|
],
|
|
});
|
|
// FindOneAndUpdate when many documents match returning the document after modification
|
|
findOneAndUpdateExecutor({
|
|
insert: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
params: [{_id: {$gt: 1}}, {$inc: {x: 1}}, {projection: {x: 1, _id: 0}, sort: {x: 1}, returnNewDocument: true}],
|
|
result: {x: 23},
|
|
expected: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 23},
|
|
{_id: 3, x: 33},
|
|
],
|
|
});
|
|
// FindOneAndUpdate when one document matches returning the document before modification
|
|
findOneAndUpdateExecutor({
|
|
insert: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
params: [{_id: 2}, {$inc: {x: 1}}, {projection: {x: 1, _id: 0}, sort: {x: 1}}],
|
|
result: {x: 22},
|
|
expected: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 23},
|
|
{_id: 3, x: 33},
|
|
],
|
|
});
|
|
// FindOneAndUpdate when one document matches returning the document after modification
|
|
findOneAndUpdateExecutor({
|
|
insert: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
params: [{_id: 2}, {$inc: {x: 1}}, {projection: {x: 1, _id: 0}, sort: {x: 1}, returnNewDocument: true}],
|
|
result: {x: 23},
|
|
expected: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 23},
|
|
{_id: 3, x: 33},
|
|
],
|
|
});
|
|
// FindOneAndUpdate when no documents match returning the document before modification
|
|
findOneAndUpdateExecutor({
|
|
insert: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
params: [{_id: 4}, {$inc: {x: 1}}, {projection: {x: 1, _id: 0}, sort: {x: 1}}],
|
|
result: null,
|
|
expected: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
});
|
|
// FindOneAndUpdate when no documents match with upsert returning the document before
|
|
// modification
|
|
findOneAndUpdateExecutor({
|
|
insert: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
params: [{_id: 4}, {$inc: {x: 1}}, {projection: {x: 1, _id: 0}, sort: {x: 1}, upsert: true}],
|
|
result: null,
|
|
expected: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
{_id: 4, x: 1},
|
|
],
|
|
});
|
|
// FindOneAndUpdate when no documents match returning the document after modification
|
|
findOneAndUpdateExecutor({
|
|
insert: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
params: [{_id: 4}, {$inc: {x: 1}}, {projection: {x: 1, _id: 0}, sort: {x: 1}, returnNewDocument: true}],
|
|
result: null,
|
|
expected: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
});
|
|
// FindOneAndUpdate when no documents match with upsert returning the document after
|
|
// modification
|
|
findOneAndUpdateExecutor({
|
|
insert: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
params: [
|
|
{_id: 4},
|
|
{$inc: {x: 1}},
|
|
{projection: {x: 1, _id: 0}, sort: {x: 1}, returnNewDocument: true, upsert: true},
|
|
],
|
|
result: {x: 1},
|
|
expected: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
{_id: 4, x: 1},
|
|
],
|
|
});
|
|
|
|
assert.throws(function () {
|
|
coll.findOneAndUpdate({a: 1}, {});
|
|
});
|
|
|
|
assert.throws(function () {
|
|
coll.findOneAndUpdate({a: 1}, {b: 1});
|
|
});
|
|
|
|
//
|
|
// InsertMany
|
|
//
|
|
|
|
// InsertMany with non-existing documents
|
|
insertManyExecutor({
|
|
insert: [{_id: 1, x: 11}],
|
|
params: [
|
|
[
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
],
|
|
result: {acknowledged: true, insertedIds: [2, 3]},
|
|
expected: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
});
|
|
// InsertMany with non-existing documents, no write concern
|
|
insertManyExecutor({
|
|
insert: [{_id: 1, x: 11}],
|
|
params: [
|
|
[
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
{w: 0},
|
|
],
|
|
result: {acknowledged: false},
|
|
expected: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
});
|
|
|
|
//
|
|
// InsertOne
|
|
//
|
|
|
|
// InsertOne with non-existing documents
|
|
insertOneExecutor({
|
|
insert: [{_id: 1, x: 11}],
|
|
params: [{_id: 2, x: 22}],
|
|
result: {acknowledged: true, insertedId: 2},
|
|
expected: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
],
|
|
});
|
|
// InsertOne with non-existing documents, no write concern
|
|
insertOneExecutor({
|
|
insert: [{_id: 1, x: 11}],
|
|
params: [{_id: 2, x: 22}, {w: 0}],
|
|
result: {acknowledged: false},
|
|
expected: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
],
|
|
});
|
|
|
|
//
|
|
// ReplaceOne
|
|
//
|
|
|
|
// ReplaceOne when many documents match
|
|
replaceOneExecutor({
|
|
insert: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
params: [{_id: {$gt: 1}}, {x: 111}],
|
|
result: {acknowledged: true, matchedCount: 1, modifiedCount: 1},
|
|
expected: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 111},
|
|
{_id: 3, x: 33},
|
|
],
|
|
});
|
|
// ReplaceOne when one document matches
|
|
replaceOneExecutor({
|
|
insert: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
params: [{_id: 1}, {_id: 1, x: 111}],
|
|
result: {acknowledged: true, matchedCount: 1, modifiedCount: 1},
|
|
expected: [
|
|
{_id: 1, x: 111},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
});
|
|
// ReplaceOne when no documents match
|
|
replaceOneExecutor({
|
|
insert: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
params: [{_id: 4}, {_id: 4, x: 1}],
|
|
result: {acknowledged: true, matchedCount: 0, modifiedCount: 0},
|
|
expected: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
});
|
|
// ReplaceOne with upsert when no documents match without an id specified
|
|
replaceOneExecutor({
|
|
insert: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
params: [{_id: 4}, {x: 1}, {upsert: true}],
|
|
result: {acknowledged: true, matchedCount: 0, modifiedCount: 0, upsertedId: 4},
|
|
expected: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
{_id: 4, x: 1},
|
|
],
|
|
});
|
|
// ReplaceOne with upsert when no documents match with an id specified
|
|
replaceOneExecutor({
|
|
insert: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
params: [{_id: 4}, {_id: 4, x: 1}, {upsert: true}],
|
|
result: {acknowledged: true, matchedCount: 0, modifiedCount: 0, upsertedId: 4},
|
|
expected: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
{_id: 4, x: 1},
|
|
],
|
|
});
|
|
// ReplaceOne with upsert when no documents match with an id specified, no write concern
|
|
replaceOneExecutor({
|
|
insert: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
params: [{_id: 4}, {_id: 4, x: 1}, {upsert: true, w: 0}],
|
|
result: {acknowledged: false},
|
|
expected: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
{_id: 4, x: 1},
|
|
],
|
|
});
|
|
// ReplaceOne with upsert when no documents match with an id specified, no write concern
|
|
replaceOneExecutor({
|
|
insert: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
params: [{_id: 4}, {_id: 4, x: 1}, {upsert: true, writeConcern: {w: 0}}],
|
|
result: {acknowledged: false},
|
|
expected: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
{_id: 4, x: 1},
|
|
],
|
|
});
|
|
|
|
assert.throws(function () {
|
|
coll.replaceOne({a: 1}, {$set: {b: 1}});
|
|
});
|
|
|
|
//
|
|
// UpdateMany
|
|
//
|
|
|
|
// UpdateMany when many documents match
|
|
updateManyExecutor({
|
|
insert: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
params: [{_id: {$gt: 1}}, {$inc: {x: 1}}],
|
|
result: {acknowledged: true, matchedCount: 2, modifiedCount: 2},
|
|
expected: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 23},
|
|
{_id: 3, x: 34},
|
|
],
|
|
});
|
|
// UpdateMany when one document matches
|
|
updateManyExecutor({
|
|
insert: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
params: [{_id: 1}, {$inc: {x: 1}}],
|
|
result: {acknowledged: true, matchedCount: 1, modifiedCount: 1},
|
|
expected: [
|
|
{_id: 1, x: 12},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
});
|
|
// UpdateMany when no documents match
|
|
updateManyExecutor({
|
|
insert: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
params: [{_id: 4}, {$inc: {x: 1}}],
|
|
result: {acknowledged: true, matchedCount: 0, modifiedCount: 0},
|
|
expected: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
});
|
|
// UpdateMany with upsert when no documents match
|
|
updateManyExecutor({
|
|
insert: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
params: [{_id: 4}, {$inc: {x: 1}}, {upsert: true}],
|
|
result: {acknowledged: true, matchedCount: 0, modifiedCount: 0, upsertedId: 4},
|
|
expected: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
{_id: 4, x: 1},
|
|
],
|
|
});
|
|
// UpdateMany with upsert when no documents match, no write concern
|
|
updateManyExecutor({
|
|
insert: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
params: [{_id: 4}, {$inc: {x: 1}}, {upsert: true, w: 0}],
|
|
result: {acknowledged: false},
|
|
expected: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
{_id: 4, x: 1},
|
|
],
|
|
});
|
|
|
|
assert.throws(function () {
|
|
coll.updateMany({a: 1}, {});
|
|
});
|
|
|
|
assert.throws(function () {
|
|
coll.updateMany({a: 1}, {b: 1});
|
|
});
|
|
|
|
//
|
|
// UpdateOne
|
|
//
|
|
|
|
// UpdateOne when many documents match
|
|
updateOneExecutor({
|
|
insert: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
params: [{_id: {$gt: 1}}, {$inc: {x: 1}}],
|
|
result: {acknowledged: true, matchedCount: 1, modifiedCount: 1},
|
|
expected: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 23},
|
|
{_id: 3, x: 33},
|
|
],
|
|
});
|
|
// UpdateOne when one document matches
|
|
updateOneExecutor({
|
|
insert: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
params: [{_id: 1}, {$inc: {x: 1}}],
|
|
result: {acknowledged: true, matchedCount: 1, modifiedCount: 1},
|
|
expected: [
|
|
{_id: 1, x: 12},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
});
|
|
// UpdateOne when no documents match
|
|
updateOneExecutor({
|
|
insert: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
params: [{_id: 4}, {$inc: {x: 1}}],
|
|
result: {acknowledged: true, matchedCount: 0, modifiedCount: 0},
|
|
expected: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
});
|
|
|
|
// UpdateOne with upsert when no documents match
|
|
updateOneExecutor({
|
|
insert: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
params: [{_id: 4}, {$inc: {x: 1}}, {upsert: true}],
|
|
result: {acknowledged: true, matchedCount: 0, modifiedCount: 0, upsertedId: 4},
|
|
expected: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
{_id: 4, x: 1},
|
|
],
|
|
});
|
|
// UpdateOne when many documents match, no write concern
|
|
updateOneExecutor({
|
|
insert: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
params: [{_id: {$gt: 1}}, {$inc: {x: 1}}, {w: 0}],
|
|
result: {acknowledged: false},
|
|
expected: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 23},
|
|
{_id: 3, x: 33},
|
|
],
|
|
});
|
|
|
|
assert.throws(function () {
|
|
coll.updateOne({a: 1}, {});
|
|
});
|
|
|
|
assert.throws(function () {
|
|
coll.updateOne({a: 1}, {b: 1});
|
|
});
|
|
|
|
//
|
|
// Count
|
|
//
|
|
|
|
// Simple count of all elements
|
|
countExecutor({
|
|
insert: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
params: [{}],
|
|
result: 3,
|
|
expected: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
});
|
|
// Simple count no arguments
|
|
countExecutor({
|
|
insert: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
params: [],
|
|
result: 3,
|
|
expected: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
});
|
|
// Simple count filtered
|
|
countExecutor({
|
|
insert: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
params: [{_id: {$gt: 1}}],
|
|
result: 2,
|
|
expected: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
});
|
|
// Simple count of all elements, applying limit
|
|
countExecutor({
|
|
insert: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
params: [{}, {limit: 1}],
|
|
result: 1,
|
|
expected: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
});
|
|
// Simple count of all elements, applying skip
|
|
countExecutor({
|
|
insert: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
params: [{}, {skip: 1}],
|
|
result: 2,
|
|
expected: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
});
|
|
// Simple count no arguments, applying hint
|
|
countExecutor({
|
|
insert: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
params: [{}, {hint: {"_id": 1}}],
|
|
result: 3,
|
|
expected: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
});
|
|
|
|
//
|
|
// Distinct
|
|
//
|
|
|
|
// Simple distinct of field x no filter
|
|
distinctExecutor({
|
|
insert: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
params: ["x"],
|
|
result: [11, 22, 33],
|
|
expected: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
});
|
|
// Simple distinct of field x
|
|
distinctExecutor({
|
|
insert: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
params: ["x", {}],
|
|
result: [11, 22, 33],
|
|
expected: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
});
|
|
// Simple distinct of field x filtered
|
|
distinctExecutor({
|
|
insert: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
params: ["x", {x: {$gt: 11}}],
|
|
result: [22, 33],
|
|
expected: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
});
|
|
// Simple distinct of field x filtered with maxTimeMS
|
|
distinctExecutor({
|
|
insert: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
params: ["x", {x: {$gt: 11}}, {maxTimeMS: 100000}],
|
|
result: [22, 33],
|
|
expected: [
|
|
{_id: 1, x: 11},
|
|
{_id: 2, x: 22},
|
|
{_id: 3, x: 33},
|
|
],
|
|
});
|
|
|
|
//
|
|
// Find
|
|
//
|
|
|
|
coll.deleteMany({});
|
|
// Insert all of them
|
|
coll.insertMany([
|
|
{a: 0, b: 0},
|
|
{a: 1, b: 1},
|
|
]);
|
|
|
|
// Simple projection
|
|
var result = coll.find({}).sort({a: 1}).limit(1).skip(1).projection({_id: 0, a: 1}).toArray();
|
|
assert.docEq([{a: 1}], result);
|
|
|
|
// Simple tailable cursor
|
|
var cursor = coll.find({}).sort({a: 1}).tailable();
|
|
assert.eq(34, cursor._options & ~DBQuery.Option.slaveOk);
|
|
var cursor = coll.find({}).sort({a: 1}).tailable(false);
|
|
assert.eq(2, cursor._options & ~DBQuery.Option.slaveOk);
|
|
|
|
// allowPartialResults
|
|
var cursor = coll.find({}).allowPartialResults();
|
|
assert.eq(128, cursor._options & ~DBQuery.Option.slaveOk);
|
|
|
|
// noCursorTimeout
|
|
var cursor = coll.find({}).noCursorTimeout();
|
|
assert.eq(16, cursor._options & ~DBQuery.Option.slaveOk);
|
|
|
|
//
|
|
// Aggregation
|
|
//
|
|
|
|
coll.deleteMany({});
|
|
// Insert all of them
|
|
coll.insertMany([
|
|
{a: 0, b: 0},
|
|
{a: 1, b: 1},
|
|
]);
|
|
|
|
// Simple aggregation with useCursor
|
|
var result = coll.aggregate([{$match: {}}], {useCursor: true}).toArray();
|
|
assert.eq(2, result.length);
|
|
|
|
// Simple aggregation with batchSize
|
|
var result = coll.aggregate([{$match: {}}], {batchSize: 2}).toArray();
|
|
assert.eq(2, result.length);
|
|
|
|
// Drop collection
|
|
coll.drop();
|
|
coll.createIndex({a: 1}, {unique: true});
|
|
|
|
// Should throw duplicate key error
|
|
assert.throws(function () {
|
|
coll.insertMany([
|
|
{a: 0, b: 0},
|
|
{a: 0, b: 1},
|
|
]);
|
|
});
|
|
|
|
assert(coll.findOne({a: 0, b: 0}) != null);
|
|
assert.throws(function () {
|
|
coll.insertOne({a: 0, b: 0});
|
|
});
|
|
|
|
assert.throws(function () {
|
|
coll.updateOne({b: 2}, {$set: {a: 0}}, {upsert: true});
|
|
});
|
|
|
|
assert.throws(function () {
|
|
coll.updateMany({b: 2}, {$set: {a: 0}}, {upsert: true});
|
|
});
|
|
|
|
assert.throws(function () {
|
|
coll.deleteOne({$invalidFieldName: {a: 1}});
|
|
});
|
|
|
|
assert.throws(function () {
|
|
coll.deleteMany({$set: {a: 1}});
|
|
});
|
|
|
|
assert.throws(function () {
|
|
coll.bulkWrite([{insertOne: {document: {_id: 4, a: 0}}}]);
|
|
});
|
|
};
|
|
|
|
crudAPISpecTests();
|