// Cannot implicitly shard accessed collections because of following errmsg: A single // update/delete on a sharded collection must contain an exact match on _id or contain the shard // key. // // @tags: [ // assumes_unsharded_collection, // assumes_write_concern_unchanged, // requires_fastcount, // # This test writes with {w: 0} which doesn't wait for the storage transaction writing the // # document and the oplog entry to commit so the TenantMigrationConflict will not be caught. // tenant_migration_incompatible, // ] (function() { "use strict"; load("jstests/aggregation/extras/utils.js"); // For arrayEq. var crudAPISpecTests = function crudAPISpecTests() { "use strict"; // Get the colllection var coll = db.crud_tests; // Setup function createTestExecutor(coll, method, verifyResult) { return function(args) { // Drop collection coll.drop(); // Insert test data var 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() { var results = coll.find({}).sort({_id: 1}).toArray(); assert.docEq(args.expected, results); return true; }, function() { return "collection never contained expected documents"; }); }; } function checkResultObject(first, second) { // Only assert on the "modifiedCount" property assert.docEq(first, second); } // Setup executors var deleteManyExecutor = createTestExecutor(coll, 'deleteMany', checkResultObject); var deleteOneExecutor = createTestExecutor(coll, 'deleteOne', checkResultObject); var bulkWriteExecutor = createTestExecutor(coll, 'bulkWrite', checkResultObject); var findOneAndDeleteExecutor = createTestExecutor(coll, 'findOneAndDelete', checkResultObject); var findOneAndReplaceExecutor = createTestExecutor(coll, 'findOneAndReplace', checkResultObject); var findOneAndUpdateExecutor = createTestExecutor(coll, 'findOneAndUpdate', checkResultObject); var insertManyExecutor = createTestExecutor(coll, 'insertMany', checkResultObject); var insertOneExecutor = createTestExecutor(coll, 'insertOne', checkResultObject); var replaceOneExecutor = createTestExecutor(coll, 'replaceOne', checkResultObject); var updateManyExecutor = createTestExecutor(coll, 'updateMany', checkResultObject); var updateOneExecutor = createTestExecutor(coll, 'updateOne', checkResultObject); var countExecutor = createTestExecutor(coll, 'count', assert.eq); var 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(result, [{a: 1}]); // 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)); // Check modifiers var cursor = coll.find({}).modifiers({$hint: 'a_1'}); assert.eq('a_1', cursor._query['$hint']); // 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(); })();