Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(NODE-6290): add sort option to UpdateOne and ReplaceOne #4229

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions src/operations/update.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 } from '../sort';
import { hasAtomicOperators, type MongoDBNamespace } from '../utils';
import { type CollationOptions, CommandOperation, type CommandOperationOptions } from './command';
import { Aspect, defineAspects, type Hint } from './operation';
Expand All @@ -22,6 +23,15 @@ export interface UpdateOptions extends CommandOperationOptions {
upsert?: boolean;
/** Map of parameter names and values that can be accessed using $$var (requires MongoDB 5.0). */
let?: Document;
/**
* Specify which document the operation updates if the query matches multiple
* documents. The first document matched by the sort order will be updated.
*
* The server will report an error if the caller explicitly provides a value with updateMany().
*
* This option is only supported by servers >= 8.0. Older servers will report an error for using this option.
*/
sort?: Document;
}

/**
Expand Down Expand Up @@ -57,6 +67,8 @@ export interface UpdateStatement {
arrayFilters?: Document[];
/** A document or string that specifies the index to use to support the query predicate. */
hint?: Hint;
/** If the query matches multiple documents, the first document matched by the sort order will be updated. */
sort?: Map<string, 1 | -1 | { $meta: string }>;
}

/**
Expand Down Expand Up @@ -207,6 +219,15 @@ 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;
/**
* Specify which document the operation replaces if the query matches multiple
* documents. The first document matched by the sort order will be replaced.
*
* The server will report an error if the caller explicitly provides a value with replaceMany().
*
* This option is only supported by servers >= 8.0. Older servers will report an error for using this option.
*/
sort?: Document;
}

/** @internal */
Expand Down Expand Up @@ -268,6 +289,10 @@ export function makeUpdateStatement(

if (options.multi) {
op.multi = options.multi;
}

if (options.sort) {
op.sort = formatSort(options?.sort);
}

if (options.hint) {
Expand Down
239 changes: 239 additions & 0 deletions test/spec/crud/unified/bulkWrite-replaceOne-sort.json
Original file line number Diff line number Diff line change
@@ -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
}
]
}
]
}
]
}
94 changes: 94 additions & 0 deletions test/spec/crud/unified/bulkWrite-replaceOne-sort.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
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 }
Loading
Loading