diff --git a/src/bulk/common.ts b/src/bulk/common.ts index e9784b6ca7c..da972d52f19 100644 --- a/src/bulk/common.ts +++ b/src/bulk/common.ts @@ -19,6 +19,7 @@ import { makeUpdateStatement, UpdateOperation, type UpdateStatement } from '../o import type { Server } from '../sdam/server'; import type { Topology } from '../sdam/topology'; import type { ClientSession } from '../sessions'; +import { type Sort } from '../sort'; import { type TimeoutContext } from '../timeout'; import { applyRetryableWrites, @@ -68,7 +69,7 @@ export interface DeleteManyModel { /** @public */ export interface ReplaceOneModel { - /** The filter to limit the replaced document. */ + /** The filter that specifies which document to replace. In the case of multiple matches, the first document matched is replaced. */ filter: Filter; /** The document with which to replace the matched document. */ replacement: WithoutId; @@ -78,11 +79,13 @@ export interface ReplaceOneModel { hint?: Hint; /** When true, creates a new document if no document matches the query. */ upsert?: boolean; + /** Specifies the sort order for the documents matched by the filter. */ + sort?: Sort; } /** @public */ export interface UpdateOneModel { - /** The filter to limit the updated documents. */ + /** The filter that specifies which document to update. In the case of multiple matches, the first document matched is updated. */ filter: Filter; /** * The modifications to apply. The value can be either: @@ -98,6 +101,8 @@ export interface UpdateOneModel { hint?: Hint; /** When true, creates a new document if no document matches the query. */ upsert?: boolean; + /** Specifies the sort order for the documents matched by the filter. */ + sort?: Sort; } /** @public */ diff --git a/src/collection.ts b/src/collection.ts index a2df98ae2da..1bdc89b2628 100644 --- a/src/collection.ts +++ b/src/collection.ts @@ -87,6 +87,7 @@ import { } from './operations/update'; import { ReadConcern, type ReadConcernLike } from './read_concern'; import { ReadPreference, type ReadPreferenceLike } from './read_preference'; +import { type Sort } from './sort'; import { DEFAULT_PK_FACTORY, MongoDBCollectionNamespace, @@ -365,7 +366,7 @@ export class Collection { async updateOne( filter: Filter, update: UpdateFilter | Document[], - options?: UpdateOptions + options?: UpdateOptions & { sort?: Sort } ): Promise> { return await executeOperation( this.client, diff --git a/src/operations/client_bulk_write/command_builder.ts b/src/operations/client_bulk_write/command_builder.ts index e4ad79d5e76..9ec3e6b029f 100644 --- a/src/operations/client_bulk_write/command_builder.ts +++ b/src/operations/client_bulk_write/command_builder.ts @@ -3,6 +3,7 @@ import { DocumentSequence } from '../../cmap/commands'; import { MongoAPIError, MongoInvalidArgumentError } from '../../error'; import { type PkFactory } from '../../mongo_client'; import type { Filter, OptionalId, UpdateFilter, WithoutId } from '../../mongo_types'; +import { formatSort, type SortForCmd } from '../../sort'; import { DEFAULT_PK_FACTORY, hasAtomicOperators } from '../../utils'; import { type CollationOptions } from '../command'; import { type Hint } from '../operation'; @@ -327,6 +328,7 @@ export interface ClientUpdateOperation { upsert?: boolean; arrayFilters?: Document[]; collation?: CollationOptions; + sort?: SortForCmd; } /** @@ -398,6 +400,9 @@ function createUpdateOperation( if (model.collation) { document.collation = model.collation; } + if (!multi && 'sort' in model && model.sort != null) { + document.sort = formatSort(model.sort); + } return document; } @@ -410,6 +415,7 @@ export interface ClientReplaceOneOperation { hint?: Hint; upsert?: boolean; collation?: CollationOptions; + sort?: SortForCmd; } /** @@ -443,6 +449,9 @@ export const buildReplaceOneOperation = ( if (model.collation) { document.collation = model.collation; } + if (model.sort != null) { + document.sort = formatSort(model.sort); + } return document; }; diff --git a/src/operations/client_bulk_write/common.ts b/src/operations/client_bulk_write/common.ts index c5b96d217ae..b08725bedae 100644 --- a/src/operations/client_bulk_write/common.ts +++ b/src/operations/client_bulk_write/common.ts @@ -2,6 +2,7 @@ import { type Document } from '../../bson'; import type { Filter, OptionalId, UpdateFilter, WithoutId } from '../../mongo_types'; import type { CollationOptions, CommandOperationOptions } from '../../operations/command'; import type { Hint } from '../../operations/operation'; +import { type Sort } from '../../sort'; /** @public */ export interface ClientBulkWriteOptions extends CommandOperationOptions { @@ -89,6 +90,8 @@ export interface ClientReplaceOneModel extends ClientWriteModel { hint?: Hint; /** When true, creates a new document if no document matches the query. */ upsert?: boolean; + /** Specifies the sort order for the documents matched by the filter. */ + sort?: Sort; } /** @public */ @@ -113,6 +116,8 @@ export interface ClientUpdateOneModel extends ClientWriteModel { hint?: Hint; /** When true, creates a new document if no document matches the query. */ upsert?: boolean; + /** Specifies the sort order for the documents matched by the filter. */ + sort?: Sort; } /** @public */ diff --git a/src/operations/update.ts b/src/operations/update.ts index 5b6f396afec..d020e2cb85e 100644 --- a/src/operations/update.ts +++ b/src/operations/update.ts @@ -4,6 +4,7 @@ import { MongoCompatibilityError, MongoInvalidArgumentError, MongoServerError } import type { InferIdType, TODO_NODE_3286 } from '../mongo_types'; import type { Server } from '../sdam/server'; import type { ClientSession } from '../sessions'; +import { formatSort, type Sort, type SortForCmd } from '../sort'; import { type TimeoutContext } from '../timeout'; import { hasAtomicOperators, type MongoDBNamespace } from '../utils'; import { type CollationOptions, CommandOperation, type CommandOperationOptions } from './command'; @@ -58,6 +59,8 @@ export interface UpdateStatement { arrayFilters?: Document[]; /** A document or string that specifies the index to use to support the query predicate. */ hint?: Hint; + /** Specifies the sort order for the documents matched by the filter. */ + sort?: SortForCmd; } /** @@ -214,6 +217,8 @@ export interface ReplaceOptions extends CommandOperationOptions { upsert?: boolean; /** Map of parameter names and values that can be accessed using $$var (requires MongoDB 5.0). */ let?: Document; + /** Specifies the sort order for the documents matched by the filter. */ + sort?: Sort; } /** @internal */ @@ -259,7 +264,7 @@ export class ReplaceOneOperation extends UpdateOperation { export function makeUpdateStatement( filter: Document, update: Document | Document[], - options: UpdateOptions & { multi?: boolean } + options: UpdateOptions & { multi?: boolean } & { sort?: Sort } ): UpdateStatement { if (filter == null || typeof filter !== 'object') { throw new MongoInvalidArgumentError('Selector must be a valid JavaScript object'); @@ -290,6 +295,10 @@ export function makeUpdateStatement( op.collation = options.collation; } + if (!options.multi && options.sort != null) { + op.sort = formatSort(options.sort); + } + return op; } diff --git a/src/sort.ts b/src/sort.ts index eb462a551e7..0b239ddd494 100644 --- a/src/sort.ts +++ b/src/sort.ts @@ -8,24 +8,24 @@ export type SortDirection = | 'desc' | 'ascending' | 'descending' - | { $meta: string }; + | { readonly $meta: string }; /** @public */ export type Sort = | string - | Exclude - | string[] - | { [key: string]: SortDirection } - | Map - | [string, SortDirection][] - | [string, SortDirection]; + | Exclude + | ReadonlyArray + | { readonly [key: string]: SortDirection } + | ReadonlyMap + | ReadonlyArray + | readonly [string, SortDirection]; /** Below stricter types were created for sort that correspond with type that the cmd takes */ -/** @internal */ +/** @public */ export type SortDirectionForCmd = 1 | -1 | { $meta: string }; -/** @internal */ +/** @public */ export type SortForCmd = Map; /** @internal */ @@ -55,7 +55,7 @@ function isMeta(t: SortDirection): t is { $meta: string } { } /** @internal */ -function isPair(t: Sort): t is [string, SortDirection] { +function isPair(t: Sort): t is readonly [string, SortDirection] { if (Array.isArray(t) && t.length === 2) { try { prepareDirection(t[1]); @@ -67,33 +67,37 @@ function isPair(t: Sort): t is [string, SortDirection] { return false; } -function isDeep(t: Sort): t is [string, SortDirection][] { +function isDeep(t: Sort): t is ReadonlyArray { return Array.isArray(t) && Array.isArray(t[0]); } -function isMap(t: Sort): t is Map { +function isMap(t: Sort): t is ReadonlyMap { return t instanceof Map && t.size > 0; } +function isReadonlyArray(value: any): value is readonly T[] { + return Array.isArray(value); +} + /** @internal */ -function pairToMap(v: [string, SortDirection]): SortForCmd { +function pairToMap(v: readonly [string, SortDirection]): SortForCmd { return new Map([[`${v[0]}`, prepareDirection([v[1]])]]); } /** @internal */ -function deepToMap(t: [string, SortDirection][]): SortForCmd { +function deepToMap(t: ReadonlyArray): SortForCmd { const sortEntries: SortPairForCmd[] = t.map(([k, v]) => [`${k}`, prepareDirection(v)]); return new Map(sortEntries); } /** @internal */ -function stringsToMap(t: string[]): SortForCmd { +function stringsToMap(t: ReadonlyArray): SortForCmd { const sortEntries: SortPairForCmd[] = t.map(key => [`${key}`, 1]); return new Map(sortEntries); } /** @internal */ -function objectToMap(t: { [key: string]: SortDirection }): SortForCmd { +function objectToMap(t: { readonly [key: string]: SortDirection }): SortForCmd { const sortEntries: SortPairForCmd[] = Object.entries(t).map(([k, v]) => [ `${k}`, prepareDirection(v) @@ -102,7 +106,7 @@ function objectToMap(t: { [key: string]: SortDirection }): SortForCmd { } /** @internal */ -function mapToMap(t: Map): SortForCmd { +function mapToMap(t: ReadonlyMap): SortForCmd { const sortEntries: SortPairForCmd[] = Array.from(t).map(([k, v]) => [ `${k}`, prepareDirection(v) @@ -116,17 +120,22 @@ export function formatSort( direction?: SortDirection ): SortForCmd | undefined { if (sort == null) return undefined; - if (typeof sort === 'string') return new Map([[sort, prepareDirection(direction)]]); + + if (typeof sort === 'string') return new Map([[sort, prepareDirection(direction)]]); // 'fieldName' + if (typeof sort !== 'object') { throw new MongoInvalidArgumentError( `Invalid sort format: ${JSON.stringify(sort)} Sort must be a valid object` ); } - if (!Array.isArray(sort)) { - return isMap(sort) ? mapToMap(sort) : Object.keys(sort).length ? objectToMap(sort) : undefined; + + if (!isReadonlyArray(sort)) { + if (isMap(sort)) return mapToMap(sort); // Map + if (Object.keys(sort).length) return objectToMap(sort); // { [fieldName: string]: SortDirection } + return undefined; } if (!sort.length) return undefined; - if (isDeep(sort)) return deepToMap(sort); - if (isPair(sort)) return pairToMap(sort); - return stringsToMap(sort); + if (isDeep(sort)) return deepToMap(sort); // [ [fieldName, sortDir], [fieldName, sortDir] ... ] + if (isPair(sort)) return pairToMap(sort); // [ fieldName, sortDir ] + return stringsToMap(sort); // [ fieldName, fieldName ] } diff --git a/test/integration/crud/client_bulk_write.test.ts b/test/integration/crud/client_bulk_write.test.ts index 0d1ce58029c..5acf6029fe3 100644 --- a/test/integration/crud/client_bulk_write.test.ts +++ b/test/integration/crud/client_bulk_write.test.ts @@ -396,4 +396,39 @@ describe('Client Bulk Write', function () { }); }); }); + + describe('sort support', () => { + describe( + 'updateMany does not support sort option', + { requires: { mongodb: '>=8.0' } }, + function () { + const commands: CommandStartedEvent[] = []; + + beforeEach(async function () { + client = this.configuration.newClient({}, { monitorCommands: true }); + + client.on('commandStarted', filterForCommands('bulkWrite', commands)); + await client.connect(); + }); + + it('should not include sort field in the command', async function () { + await client.bulkWrite([ + { + name: 'updateMany', + namespace: 'foo.bar', + filter: { age: { $lte: 5 } }, + update: { $set: { puppy: true } }, + // @ts-expect-error: sort is not supported in updateMany + sort: { age: 1 } // This sort option should be ignored + } + ]); + + expect(commands).to.have.lengthOf(1); + const [updateCommand] = commands; + expect(updateCommand.commandName).to.equal('bulkWrite'); + expect(updateCommand.command.ops[0]).to.not.have.property('sort'); + }); + } + ); + }); }); diff --git a/test/integration/crud/crud_api.test.ts b/test/integration/crud/crud_api.test.ts index ac60b2901a6..2f82c6164c1 100644 --- a/test/integration/crud/crud_api.test.ts +++ b/test/integration/crud/crud_api.test.ts @@ -6,6 +6,7 @@ import { finished } from 'stream/promises'; import { Collection, CommandFailedEvent, + type CommandStartedEvent, CommandSucceededEvent, MongoBulkWriteError, type MongoClient, @@ -1152,4 +1153,53 @@ describe('CRUD API', function () { }); } }); + + describe('sort support', function () { + let client: MongoClient; + let events: Array; + let collection: Collection; + + beforeEach(async function () { + client = this.configuration.newClient({ monitorCommands: true }); + events = []; + client.on('commandStarted', commandStarted => + commandStarted.commandName === 'update' ? events.push(commandStarted) : null + ); + + collection = client.db('updateManyTest').collection('updateManyTest'); + await collection.drop().catch(() => null); + await collection.insertMany([{ a: 1 }, { a: 2 }]); + }); + + afterEach(async function () { + await collection.drop().catch(() => null); + await client.close(); + }); + + describe('collection.updateMany()', () => { + it('does not attach a sort property if one is specified', async function () { + // @ts-expect-error: sort is not supported + await collection.updateMany({ a: { $gte: 1 } }, { $set: { b: 1 } }, { sort: { a: 1 } }); + + expect(events).to.have.lengthOf(1); + const [updateEvent] = events; + expect(updateEvent.commandName).to.equal('update'); + expect(updateEvent.command.updates[0]).to.not.have.property('sort'); + }); + }); + + describe('collection.bulkWrite([{updateMany}])', () => { + it('does not attach a sort property if one is specified', async function () { + await collection.bulkWrite([ + // @ts-expect-error: sort is not supported + { updateMany: { filter: { a: { $gte: 1 } }, update: { $set: { b: 1 } }, sort: { a: 1 } } } + ]); + + expect(events).to.have.lengthOf(1); + const [updateEvent] = events; + expect(updateEvent.commandName).to.equal('update'); + expect(updateEvent.command.updates[0]).to.not.have.property('sort'); + }); + }); + }); }); diff --git a/test/spec/crud/unified/bulkWrite-replaceOne-sort.json b/test/spec/crud/unified/bulkWrite-replaceOne-sort.json new file mode 100644 index 00000000000..c0bd3835142 --- /dev/null +++ b/test/spec/crud/unified/bulkWrite-replaceOne-sort.json @@ -0,0 +1,239 @@ +{ + "description": "BulkWrite replaceOne-sort", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0", + "observeEvents": [ + "commandStartedEvent", + "commandSucceededEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "crud-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll0" + } + } + ], + "initialData": [ + { + "collectionName": "coll0", + "databaseName": "crud-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ], + "tests": [ + { + "description": "BulkWrite replaceOne with sort option", + "runOnRequirements": [ + { + "minServerVersion": "8.0" + } + ], + "operations": [ + { + "object": "collection0", + "name": "bulkWrite", + "arguments": { + "requests": [ + { + "replaceOne": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "sort": { + "_id": -1 + }, + "replacement": { + "x": 1 + } + } + } + ] + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "update": "coll0", + "updates": [ + { + "q": { + "_id": { + "$gt": 1 + } + }, + "u": { + "x": 1 + }, + "sort": { + "_id": -1 + }, + "multi": { + "$$unsetOrMatches": false + }, + "upsert": { + "$$unsetOrMatches": false + } + } + ] + } + } + }, + { + "commandSucceededEvent": { + "reply": { + "ok": 1, + "n": 1 + }, + "commandName": "update" + } + } + ] + } + ], + "outcome": [ + { + "collectionName": "coll0", + "databaseName": "crud-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 1 + } + ] + } + ] + }, + { + "description": "BulkWrite replaceOne with sort option unsupported (server-side error)", + "runOnRequirements": [ + { + "maxServerVersion": "7.99" + } + ], + "operations": [ + { + "object": "collection0", + "name": "bulkWrite", + "arguments": { + "requests": [ + { + "replaceOne": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "sort": { + "_id": -1 + }, + "replacement": { + "x": 1 + } + } + } + ] + }, + "expectError": { + "isClientError": false + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "update": "coll0", + "updates": [ + { + "q": { + "_id": { + "$gt": 1 + } + }, + "u": { + "x": 1 + }, + "sort": { + "_id": -1 + }, + "multi": { + "$$unsetOrMatches": false + }, + "upsert": { + "$$unsetOrMatches": false + } + } + ] + } + } + } + ] + } + ], + "outcome": [ + { + "collectionName": "coll0", + "databaseName": "crud-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ] + } + ] +} diff --git a/test/spec/crud/unified/bulkWrite-replaceOne-sort.yml b/test/spec/crud/unified/bulkWrite-replaceOne-sort.yml new file mode 100644 index 00000000000..6f326fe043c --- /dev/null +++ b/test/spec/crud/unified/bulkWrite-replaceOne-sort.yml @@ -0,0 +1,94 @@ +description: BulkWrite replaceOne-sort + +schemaVersion: "1.0" + +createEntities: + - client: + id: &client0 client0 + observeEvents: [ commandStartedEvent, commandSucceededEvent ] + - database: + id: &database0 database0 + client: *client0 + databaseName: &database0Name crud-tests + - collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection0Name coll0 + +initialData: + - collectionName: *collection0Name + databaseName: *database0Name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + +tests: + - description: BulkWrite replaceOne with sort option + runOnRequirements: + - minServerVersion: "8.0" + operations: + - object: *collection0 + name: bulkWrite + arguments: + requests: + - replaceOne: + filter: { _id: { $gt: 1 } } + sort: { _id: -1 } + replacement: { x: 1 } + expectEvents: + - client: *client0 + events: + - commandStartedEvent: + command: + update: *collection0Name + updates: + - q: { _id: { $gt: 1 } } + u: { x: 1 } + sort: { _id: -1 } + multi: { $$unsetOrMatches: false } + upsert: { $$unsetOrMatches: false } + - commandSucceededEvent: + reply: { ok: 1, n: 1 } + commandName: update + outcome: + - collectionName: *collection0Name + databaseName: *database0Name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 1 } + + - description: BulkWrite replaceOne with sort option unsupported (server-side error) + runOnRequirements: + - maxServerVersion: "7.99" + operations: + - object: *collection0 + name: bulkWrite + arguments: + requests: + - replaceOne: + filter: { _id: { $gt: 1 } } + sort: { _id: -1 } + replacement: { x: 1 } + expectError: + isClientError: false + expectEvents: + - client: *client0 + events: + - commandStartedEvent: + command: + update: *collection0Name + updates: + - q: { _id: { $gt: 1 } } + u: { x: 1 } + sort: { _id: -1 } + multi: { $$unsetOrMatches: false } + upsert: { $$unsetOrMatches: false } + outcome: + - collectionName: *collection0Name + databaseName: *database0Name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } diff --git a/test/spec/crud/unified/bulkWrite-updateOne-sort.json b/test/spec/crud/unified/bulkWrite-updateOne-sort.json new file mode 100644 index 00000000000..f78bd3bf3e3 --- /dev/null +++ b/test/spec/crud/unified/bulkWrite-updateOne-sort.json @@ -0,0 +1,255 @@ +{ + "description": "BulkWrite updateOne-sort", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0", + "observeEvents": [ + "commandStartedEvent", + "commandSucceededEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "crud-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll0" + } + } + ], + "initialData": [ + { + "collectionName": "coll0", + "databaseName": "crud-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ], + "tests": [ + { + "description": "BulkWrite updateOne with sort option", + "runOnRequirements": [ + { + "minServerVersion": "8.0" + } + ], + "operations": [ + { + "object": "collection0", + "name": "bulkWrite", + "arguments": { + "requests": [ + { + "updateOne": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "sort": { + "_id": -1 + }, + "update": [ + { + "$set": { + "x": 1 + } + } + ] + } + } + ] + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "update": "coll0", + "updates": [ + { + "q": { + "_id": { + "$gt": 1 + } + }, + "u": [ + { + "$set": { + "x": 1 + } + } + ], + "sort": { + "_id": -1 + }, + "multi": { + "$$unsetOrMatches": false + }, + "upsert": { + "$$unsetOrMatches": false + } + } + ] + } + } + }, + { + "commandSucceededEvent": { + "reply": { + "ok": 1, + "n": 1 + }, + "commandName": "update" + } + } + ] + } + ], + "outcome": [ + { + "collectionName": "coll0", + "databaseName": "crud-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 1 + } + ] + } + ] + }, + { + "description": "BulkWrite updateOne with sort option unsupported (server-side error)", + "runOnRequirements": [ + { + "maxServerVersion": "7.99" + } + ], + "operations": [ + { + "object": "collection0", + "name": "bulkWrite", + "arguments": { + "requests": [ + { + "updateOne": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "sort": { + "_id": -1 + }, + "update": [ + { + "$set": { + "x": 1 + } + } + ] + } + } + ] + }, + "expectError": { + "isClientError": false + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "update": "coll0", + "updates": [ + { + "q": { + "_id": { + "$gt": 1 + } + }, + "u": [ + { + "$set": { + "x": 1 + } + } + ], + "sort": { + "_id": -1 + }, + "multi": { + "$$unsetOrMatches": false + }, + "upsert": { + "$$unsetOrMatches": false + } + } + ] + } + } + } + ] + } + ], + "outcome": [ + { + "collectionName": "coll0", + "databaseName": "crud-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ] + } + ] +} diff --git a/test/spec/crud/unified/bulkWrite-updateOne-sort.yml b/test/spec/crud/unified/bulkWrite-updateOne-sort.yml new file mode 100644 index 00000000000..72bc814d69e --- /dev/null +++ b/test/spec/crud/unified/bulkWrite-updateOne-sort.yml @@ -0,0 +1,94 @@ +description: BulkWrite updateOne-sort + +schemaVersion: "1.0" + +createEntities: + - client: + id: &client0 client0 + observeEvents: [ commandStartedEvent, commandSucceededEvent ] + - database: + id: &database0 database0 + client: *client0 + databaseName: &database0Name crud-tests + - collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection0Name coll0 + +initialData: + - collectionName: *collection0Name + databaseName: *database0Name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + +tests: + - description: BulkWrite updateOne with sort option + runOnRequirements: + - minServerVersion: "8.0" + operations: + - object: *collection0 + name: bulkWrite + arguments: + requests: + - updateOne: + filter: { _id: { $gt: 1 } } + sort: { _id: -1 } + update: [ $set: { x: 1 } ] + expectEvents: + - client: *client0 + events: + - commandStartedEvent: + command: + update: *collection0Name + updates: + - q: { _id: { $gt: 1 } } + u: [ $set: { x: 1 } ] + sort: { _id: -1 } + multi: { $$unsetOrMatches: false } + upsert: { $$unsetOrMatches: false } + - commandSucceededEvent: + reply: { ok: 1, n: 1 } + commandName: update + outcome: + - collectionName: *collection0Name + databaseName: *database0Name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 1 } + + - description: BulkWrite updateOne with sort option unsupported (server-side error) + runOnRequirements: + - maxServerVersion: "7.99" + operations: + - object: *collection0 + name: bulkWrite + arguments: + requests: + - updateOne: + filter: { _id: { $gt: 1 } } + sort: { _id: -1 } + update: [ $set: { x: 1 } ] + expectError: + isClientError: false + expectEvents: + - client: *client0 + events: + - commandStartedEvent: + command: + update: *collection0Name + updates: + - q: { _id: { $gt: 1 } } + u: [ $set: { x: 1 } ] + sort: { _id: -1 } + multi: { $$unsetOrMatches: false } + upsert: { $$unsetOrMatches: false } + outcome: + - collectionName: *collection0Name + databaseName: *database0Name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } diff --git a/test/spec/crud/unified/client-bulkWrite-replaceOne-sort.json b/test/spec/crud/unified/client-bulkWrite-replaceOne-sort.json new file mode 100644 index 00000000000..fc66ec015d3 --- /dev/null +++ b/test/spec/crud/unified/client-bulkWrite-replaceOne-sort.json @@ -0,0 +1,163 @@ +{ + "description": "client bulkWrite replaceOne-sort", + "schemaVersion": "1.4", + "runOnRequirements": [ + { + "minServerVersion": "8.0", + "serverless": "forbid" + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "observeEvents": [ + "commandStartedEvent", + "commandSucceededEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "crud-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll0" + } + } + ], + "initialData": [ + { + "collectionName": "coll0", + "databaseName": "crud-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ], + "_yamlAnchors": { + "namespace": "crud-tests.coll0" + }, + "tests": [ + { + "description": "client bulkWrite replaceOne with sort option", + "operations": [ + { + "object": "client0", + "name": "clientBulkWrite", + "arguments": { + "models": [ + { + "replaceOne": { + "namespace": "crud-tests.coll0", + "filter": { + "_id": { + "$gt": 1 + } + }, + "sort": { + "_id": -1 + }, + "replacement": { + "x": 1 + } + } + } + ] + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "commandName": "bulkWrite", + "databaseName": "admin", + "command": { + "bulkWrite": 1, + "ops": [ + { + "update": 0, + "filter": { + "_id": { + "$gt": 1 + } + }, + "updateMods": { + "x": 1 + }, + "sort": { + "_id": -1 + }, + "multi": { + "$$unsetOrMatches": false + }, + "upsert": { + "$$unsetOrMatches": false + } + } + ], + "nsInfo": [ + { + "ns": "crud-tests.coll0" + } + ] + } + } + }, + { + "commandSucceededEvent": { + "reply": { + "ok": 1, + "nErrors": 0, + "nMatched": 1, + "nModified": 1 + }, + "commandName": "bulkWrite" + } + } + ] + } + ], + "outcome": [ + { + "collectionName": "coll0", + "databaseName": "crud-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 1 + } + ] + } + ] + } + ] +} diff --git a/test/spec/crud/unified/client-bulkWrite-replaceOne-sort.yml b/test/spec/crud/unified/client-bulkWrite-replaceOne-sort.yml new file mode 100644 index 00000000000..1ea47abc4c8 --- /dev/null +++ b/test/spec/crud/unified/client-bulkWrite-replaceOne-sort.yml @@ -0,0 +1,77 @@ +description: client bulkWrite replaceOne-sort + +schemaVersion: "1.4" + +runOnRequirements: + - minServerVersion: "8.0" + serverless: forbid # Serverless does not support bulkWrite: CLOUDP-256344. + +createEntities: + - client: + id: &client0 client0 + observeEvents: + - commandStartedEvent + - commandSucceededEvent + - database: + id: &database0 database0 + client: *client0 + databaseName: &database0Name crud-tests + - collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection0Name coll0 + +initialData: + - collectionName: *collection0Name + databaseName: *database0Name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + +_yamlAnchors: + namespace: &namespace "crud-tests.coll0" + +tests: + - description: client bulkWrite replaceOne with sort option + operations: + - object: *client0 + name: clientBulkWrite + arguments: + models: + - replaceOne: + namespace: *namespace + filter: { _id: { $gt: 1 } } + sort: { _id: -1 } + replacement: { x: 1 } + expectEvents: + - client: *client0 + events: + - commandStartedEvent: + commandName: bulkWrite + databaseName: admin + command: + bulkWrite: 1 + ops: + - update: 0 + filter: { _id: { $gt: 1 } } + updateMods: { x: 1 } + sort: { _id: -1 } + multi: { $$unsetOrMatches: false } + upsert: { $$unsetOrMatches: false } + nsInfo: + - ns: *namespace + - commandSucceededEvent: + reply: + ok: 1 + nErrors: 0 + nMatched: 1 + nModified: 1 + commandName: bulkWrite + outcome: + - collectionName: *collection0Name + databaseName: *database0Name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 1 } diff --git a/test/spec/crud/unified/client-bulkWrite-updateOne-sort.json b/test/spec/crud/unified/client-bulkWrite-updateOne-sort.json new file mode 100644 index 00000000000..ef75dcb3741 --- /dev/null +++ b/test/spec/crud/unified/client-bulkWrite-updateOne-sort.json @@ -0,0 +1,167 @@ +{ + "description": "client bulkWrite updateOne-sort", + "schemaVersion": "1.4", + "runOnRequirements": [ + { + "minServerVersion": "8.0", + "serverless": "forbid" + } + ], + "createEntities": [ + { + "client": { + "id": "client0", + "observeEvents": [ + "commandStartedEvent", + "commandSucceededEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "crud-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll0" + } + } + ], + "initialData": [ + { + "collectionName": "coll0", + "databaseName": "crud-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ], + "_yamlAnchors": { + "namespace": "crud-tests.coll0" + }, + "tests": [ + { + "description": "client bulkWrite updateOne with sort option", + "operations": [ + { + "object": "client0", + "name": "clientBulkWrite", + "arguments": { + "models": [ + { + "updateOne": { + "namespace": "crud-tests.coll0", + "filter": { + "_id": { + "$gt": 1 + } + }, + "sort": { + "_id": -1 + }, + "update": { + "$inc": { + "x": 1 + } + } + } + } + ] + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "commandName": "bulkWrite", + "databaseName": "admin", + "command": { + "bulkWrite": 1, + "ops": [ + { + "update": 0, + "filter": { + "_id": { + "$gt": 1 + } + }, + "updateMods": { + "$inc": { + "x": 1 + } + }, + "sort": { + "_id": -1 + }, + "multi": { + "$$unsetOrMatches": false + }, + "upsert": { + "$$unsetOrMatches": false + } + } + ], + "nsInfo": [ + { + "ns": "crud-tests.coll0" + } + ] + } + } + }, + { + "commandSucceededEvent": { + "reply": { + "ok": 1, + "nErrors": 0, + "nMatched": 1, + "nModified": 1 + }, + "commandName": "bulkWrite" + } + } + ] + } + ], + "outcome": [ + { + "collectionName": "coll0", + "databaseName": "crud-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 34 + } + ] + } + ] + } + ] +} diff --git a/test/spec/crud/unified/client-bulkWrite-updateOne-sort.yml b/test/spec/crud/unified/client-bulkWrite-updateOne-sort.yml new file mode 100644 index 00000000000..73a265d6b87 --- /dev/null +++ b/test/spec/crud/unified/client-bulkWrite-updateOne-sort.yml @@ -0,0 +1,77 @@ +description: client bulkWrite updateOne-sort + +schemaVersion: "1.4" + +runOnRequirements: + - minServerVersion: "8.0" + serverless: forbid # Serverless does not support bulkWrite: CLOUDP-256344. + +createEntities: + - client: + id: &client0 client0 + observeEvents: + - commandStartedEvent + - commandSucceededEvent + - database: + id: &database0 database0 + client: *client0 + databaseName: &database0Name crud-tests + - collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection0Name coll0 + +initialData: + - collectionName: *collection0Name + databaseName: *database0Name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + +_yamlAnchors: + namespace: &namespace "crud-tests.coll0" + +tests: + - description: client bulkWrite updateOne with sort option + operations: + - object: *client0 + name: clientBulkWrite + arguments: + models: + - updateOne: + namespace: *namespace + filter: { _id: { $gt: 1 } } + sort: { _id: -1 } + update: { $inc: { x: 1 } } + expectEvents: + - client: *client0 + events: + - commandStartedEvent: + commandName: bulkWrite + databaseName: admin + command: + bulkWrite: 1 + ops: + - update: 0 + filter: { _id: { $gt: 1 } } + updateMods: { $inc: { x: 1 } } + sort: { _id: -1 } + multi: { $$unsetOrMatches: false } + upsert: { $$unsetOrMatches: false } + nsInfo: + - ns: *namespace + - commandSucceededEvent: + reply: + ok: 1 + nErrors: 0 + nMatched: 1 + nModified: 1 + commandName: bulkWrite + outcome: + - collectionName: *collection0Name + databaseName: *database0Name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 34 } diff --git a/test/spec/crud/unified/replaceOne-sort.json b/test/spec/crud/unified/replaceOne-sort.json new file mode 100644 index 00000000000..cf2271dda57 --- /dev/null +++ b/test/spec/crud/unified/replaceOne-sort.json @@ -0,0 +1,232 @@ +{ + "description": "replaceOne-sort", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0", + "observeEvents": [ + "commandStartedEvent", + "commandSucceededEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "crud-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll0" + } + } + ], + "initialData": [ + { + "collectionName": "coll0", + "databaseName": "crud-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ], + "tests": [ + { + "description": "ReplaceOne with sort option", + "runOnRequirements": [ + { + "minServerVersion": "8.0" + } + ], + "operations": [ + { + "name": "replaceOne", + "object": "collection0", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "sort": { + "_id": -1 + }, + "replacement": { + "x": 1 + } + }, + "expectResult": { + "matchedCount": 1, + "modifiedCount": 1, + "upsertedCount": 0 + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "update": "coll0", + "updates": [ + { + "q": { + "_id": { + "$gt": 1 + } + }, + "u": { + "x": 1 + }, + "sort": { + "_id": -1 + }, + "multi": { + "$$unsetOrMatches": false + }, + "upsert": { + "$$unsetOrMatches": false + } + } + ] + } + } + }, + { + "commandSucceededEvent": { + "reply": { + "ok": 1, + "n": 1 + }, + "commandName": "update" + } + } + ] + } + ], + "outcome": [ + { + "collectionName": "coll0", + "databaseName": "crud-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 1 + } + ] + } + ] + }, + { + "description": "replaceOne with sort option unsupported (server-side error)", + "runOnRequirements": [ + { + "maxServerVersion": "7.99" + } + ], + "operations": [ + { + "name": "replaceOne", + "object": "collection0", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "sort": { + "_id": -1 + }, + "replacement": { + "x": 1 + } + }, + "expectError": { + "isClientError": false + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "update": "coll0", + "updates": [ + { + "q": { + "_id": { + "$gt": 1 + } + }, + "u": { + "x": 1 + }, + "sort": { + "_id": -1 + }, + "multi": { + "$$unsetOrMatches": false + }, + "upsert": { + "$$unsetOrMatches": false + } + } + ] + } + } + } + ] + } + ], + "outcome": [ + { + "collectionName": "coll0", + "databaseName": "crud-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ] + } + ] +} diff --git a/test/spec/crud/unified/replaceOne-sort.yml b/test/spec/crud/unified/replaceOne-sort.yml new file mode 100644 index 00000000000..f4b10fbaf98 --- /dev/null +++ b/test/spec/crud/unified/replaceOne-sort.yml @@ -0,0 +1,94 @@ +description: replaceOne-sort + +schemaVersion: "1.0" + +createEntities: + - client: + id: &client0 client0 + observeEvents: [ commandStartedEvent, commandSucceededEvent ] + - database: + id: &database0 database0 + client: *client0 + databaseName: &database0Name crud-tests + - collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection0Name coll0 + +initialData: + - collectionName: *collection0Name + databaseName: *database0Name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + +tests: + - description: ReplaceOne with sort option + runOnRequirements: + - minServerVersion: "8.0" + operations: + - name: replaceOne + object: *collection0 + arguments: + filter: { _id: { $gt: 1 } } + sort: { _id: -1 } + replacement: { x: 1 } + expectResult: + matchedCount: 1 + modifiedCount: 1 + upsertedCount: 0 + expectEvents: + - client: *client0 + events: + - commandStartedEvent: + command: + update: *collection0Name + updates: + - q: { _id: { $gt: 1 } } + u: { x: 1 } + sort: { _id: -1 } + multi: { $$unsetOrMatches: false } + upsert: { $$unsetOrMatches: false } + - commandSucceededEvent: + reply: { ok: 1, n: 1 } + commandName: update + outcome: + - collectionName: *collection0Name + databaseName: *database0Name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 1 } + + - description: replaceOne with sort option unsupported (server-side error) + runOnRequirements: + - maxServerVersion: "7.99" + operations: + - name: replaceOne + object: *collection0 + arguments: + filter: { _id: { $gt: 1 } } + sort: { _id: -1 } + replacement: { x: 1 } + expectError: + isClientError: false + expectEvents: + - client: *client0 + events: + - commandStartedEvent: + command: + update: *collection0Name + updates: + - q: { _id: { $gt: 1 } } + u: { x: 1 } + sort: { _id: -1 } + multi: { $$unsetOrMatches: false } + upsert: { $$unsetOrMatches: false } + outcome: + - collectionName: *collection0Name + databaseName: *database0Name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } diff --git a/test/spec/crud/unified/updateOne-sort.json b/test/spec/crud/unified/updateOne-sort.json new file mode 100644 index 00000000000..8fe4f50b94f --- /dev/null +++ b/test/spec/crud/unified/updateOne-sort.json @@ -0,0 +1,240 @@ +{ + "description": "updateOne-sort", + "schemaVersion": "1.0", + "createEntities": [ + { + "client": { + "id": "client0", + "observeEvents": [ + "commandStartedEvent", + "commandSucceededEvent" + ] + } + }, + { + "database": { + "id": "database0", + "client": "client0", + "databaseName": "crud-tests" + } + }, + { + "collection": { + "id": "collection0", + "database": "database0", + "collectionName": "coll0" + } + } + ], + "initialData": [ + { + "collectionName": "coll0", + "databaseName": "crud-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ], + "tests": [ + { + "description": "UpdateOne with sort option", + "runOnRequirements": [ + { + "minServerVersion": "8.0" + } + ], + "operations": [ + { + "name": "updateOne", + "object": "collection0", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "sort": { + "_id": -1 + }, + "update": { + "$inc": { + "x": 1 + } + } + }, + "expectResult": { + "matchedCount": 1, + "modifiedCount": 1, + "upsertedCount": 0 + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "update": "coll0", + "updates": [ + { + "q": { + "_id": { + "$gt": 1 + } + }, + "u": { + "$inc": { + "x": 1 + } + }, + "sort": { + "_id": -1 + }, + "multi": { + "$$unsetOrMatches": false + }, + "upsert": { + "$$unsetOrMatches": false + } + } + ] + } + } + }, + { + "commandSucceededEvent": { + "reply": { + "ok": 1, + "n": 1 + }, + "commandName": "update" + } + } + ] + } + ], + "outcome": [ + { + "collectionName": "coll0", + "databaseName": "crud-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 34 + } + ] + } + ] + }, + { + "description": "updateOne with sort option unsupported (server-side error)", + "runOnRequirements": [ + { + "maxServerVersion": "7.99" + } + ], + "operations": [ + { + "name": "updateOne", + "object": "collection0", + "arguments": { + "filter": { + "_id": { + "$gt": 1 + } + }, + "sort": { + "_id": -1 + }, + "update": { + "$inc": { + "x": 1 + } + } + }, + "expectError": { + "isClientError": false + } + } + ], + "expectEvents": [ + { + "client": "client0", + "events": [ + { + "commandStartedEvent": { + "command": { + "update": "coll0", + "updates": [ + { + "q": { + "_id": { + "$gt": 1 + } + }, + "u": { + "$inc": { + "x": 1 + } + }, + "sort": { + "_id": -1 + }, + "multi": { + "$$unsetOrMatches": false + }, + "upsert": { + "$$unsetOrMatches": false + } + } + ] + } + } + } + ] + } + ], + "outcome": [ + { + "collectionName": "coll0", + "databaseName": "crud-tests", + "documents": [ + { + "_id": 1, + "x": 11 + }, + { + "_id": 2, + "x": 22 + }, + { + "_id": 3, + "x": 33 + } + ] + } + ] + } + ] +} diff --git a/test/spec/crud/unified/updateOne-sort.yml b/test/spec/crud/unified/updateOne-sort.yml new file mode 100644 index 00000000000..a14e1df1d2b --- /dev/null +++ b/test/spec/crud/unified/updateOne-sort.yml @@ -0,0 +1,96 @@ +description: updateOne-sort + +schemaVersion: "1.0" + +createEntities: + - client: + id: &client0 client0 + observeEvents: + - commandStartedEvent + - commandSucceededEvent + - database: + id: &database0 database0 + client: *client0 + databaseName: &database0Name crud-tests + - collection: + id: &collection0 collection0 + database: *database0 + collectionName: &collection0Name coll0 + +initialData: + - collectionName: *collection0Name + databaseName: *database0Name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } + +tests: + - description: UpdateOne with sort option + runOnRequirements: + - minServerVersion: "8.0" + operations: + - name: updateOne + object: *collection0 + arguments: + filter: { _id: { $gt: 1 } } + sort: { _id: -1 } + update: { $inc: { x: 1 } } + expectResult: + matchedCount: 1 + modifiedCount: 1 + upsertedCount: 0 + expectEvents: + - client: *client0 + events: + - commandStartedEvent: + command: + update: *collection0Name + updates: + - q: { _id: { $gt: 1 } } + u: { $inc: { x: 1 } } + sort: { _id: -1 } + multi: { $$unsetOrMatches: false } + upsert: { $$unsetOrMatches: false } + - commandSucceededEvent: + reply: { ok: 1, n: 1 } + commandName: update + outcome: + - collectionName: *collection0Name + databaseName: *database0Name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 34 } + + - description: updateOne with sort option unsupported (server-side error) + runOnRequirements: + - maxServerVersion: "7.99" + operations: + - name: updateOne + object: *collection0 + arguments: + filter: { _id: { $gt: 1 } } + sort: { _id: -1 } + update: { $inc: { x: 1 } } + expectError: + isClientError: false + expectEvents: + - client: *client0 + events: + - commandStartedEvent: + command: + update: *collection0Name + updates: + - q: { _id: { $gt: 1 } } + u: { $inc: { x: 1 } } + sort: { _id: -1 } + multi: { $$unsetOrMatches: false } + upsert: { $$unsetOrMatches: false } + outcome: + - collectionName: *collection0Name + databaseName: *database0Name + documents: + - { _id: 1, x: 11 } + - { _id: 2, x: 22 } + - { _id: 3, x: 33 } diff --git a/test/types/sort.test-d.ts b/test/types/sort.test-d.ts new file mode 100644 index 00000000000..63f7bc3efe7 --- /dev/null +++ b/test/types/sort.test-d.ts @@ -0,0 +1,108 @@ +import { expectError } from 'tsd'; + +import { + type Collection, + type GridFSBucket, + type MongoClient, + ObjectId, + type Sort +} from '../mongodb'; + +const sortFieldName: Sort = 'a'; +const sortFieldNameObject: Sort = { a: 1, b: -1 }; +const sortFieldNameList: Sort = ['a', 'b']; +const sortFieldNameTuple: Sort = ['a', 1]; +const sortFieldNameTuples: Sort = [ + ['a', 1], + ['b', -1] +]; +const sortFieldNameMap: Sort = new Map([ + ['a', 1], + ['b', -1] +]); + +const sorts = [ + // field names + 'a', + 'b', + + // sort object + { a: 1, b: -1 } as const, + { a: 'ascending', b: 'ascending' } as const, + { a: 'asc', b: 'desc' } as const, + { a: 1, b: { $meta: 'textScore' } } as const, + + // field name list + ['a', 'b'], + ['a'], + + // field name to sort direction tuple + ['a', 1] as const, + ['a', -1] as const, + ['a', 'asc'] as const, + ['a', 'desc'] as const, + ['a', 'ascending'] as const, + ['a', 'descending'] as const, + ['a', { $meta: 'textScore' }] as const, + + // field name to sort direction tuples + [ + ['a', 1], + ['b', -1] + ] as const, + [ + ['a', 'ascending'], + ['b', 'ascending'] + ] as const, + [ + ['a', 'asc'], + ['b', 'desc'] + ] as const, + [ + ['a', 1], + ['b', { $meta: 'textScore' }] + ] as const, + + // field name to sort direction map + new Map().set('a', 1).set('b', -1), + new Map().set('a', 'ascending').set('b', 'ascending'), + new Map().set('a', 'asc').set('b', 'desc'), + new Map().set('a', 1).set('b', { $meta: 'textScore' }) +]; + +declare const bucket: GridFSBucket; +declare const collection: Collection; +declare const client: MongoClient; +declare const anyIndex: number; +const sort = sorts[anyIndex]; + +collection.findOne({}, { sort }); +collection.find({}, { sort }); +collection.find({}).sort(sort); + +collection.aggregate([]).sort(sort); + +collection.findOneAndDelete({}, { sort }); +collection.findOneAndReplace({}, { sort }); +collection.findOneAndUpdate({}, { sort }); + +bucket.openDownloadStream(new ObjectId(), { sort }); +bucket.openDownloadStreamByName('', { sort }); + +collection.updateOne({}, {}, { sort }); +collection.replaceOne({}, {}, { sort }); + +collection.bulkWrite([{ updateOne: { filter: {}, update: {}, sort } }]); +collection.bulkWrite([{ replaceOne: { filter: {}, replacement: {}, sort } }]); + +client.bulkWrite([ + { name: 'updateOne', namespace: 'blah', filter: {}, update: {}, sort }, + { name: 'replaceOne', namespace: 'blah', filter: {}, replacement: {}, sort } +]); + +// UpdateMany does not support sort +expectError(collection.updateMany({}, {}, { sort })); +expectError( + client.bulkWrite([{ name: 'updateMany', namespace: 'blah', filter: {}, update: {}, sort }]) +); +expectError(collection.bulkWrite([{ updateMany: { filter: {}, update: {}, sort } }]));