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-6350): add typescript support to client bulkWrite API #4257

Merged
merged 11 commits into from
Oct 20, 2024

Conversation

nbbeeken
Copy link
Contributor

@nbbeeken nbbeeken commented Sep 30, 2024

Description

What is changing?

  • Adds namespace to schema mapping type

  • Adds tests/examples to our tsd tests

  • Some important choices:

    • We should default only where needed ("near the top"), the Models now require an input schema, Document can be used when none is needed.
    • ClientBulkWriteModel is exported on its own and is not an array type. We can offer this seperate from the client API so annotations can be used to get this string to schema behavior (but I would advocate for putting it directly into the API)
Is there new documentation needed for these changes?

Yes, I think the API doc on client.bulkWrite should explain how to use the TS a bit. I started in the TS doc for ClientBulkWriteModel

We mostly use "inline" models to demo the API, however, this TS change does not cause friction in wrapping this API, it does have some considerations though, if you make a helper that returns InsertOneModels you will want the return type to still preserve the type of "namespace" where appropriate to get autocomplete and assertions. -- we should write a small example of this.

What is the motivation for this change?

Users of this method can get thier schema asserted on the various bulkWrite models making sure input data is not adjusted accidentally or that filters aren't written in a way that doees not match the data format at all.

Release Highlight

New client bulk write API supported

A new bulk write API on the MongoClient is now supported for users on server versions 8.0 and higher.
This API is meant to replace the existing bulk write API on the Collection as it supports a bulk
write across multiple databases and collections in a single call.

Usage

Users of this API call MongoClient#bulkWrite and provide a list of bulk write models and options.
The models have a structure as follows:

Insert One

Note that when no _id field is provided in the document, the driver will generate a BSON ObjectId
automatically.

{
  namespace: '<db>.<collection>',
  name: 'insertOne',
  document: Document
}

Update One

{
  namespace: '<db>.<collection>',
  name: 'updateOne',
  filter: Document,
  update: Document | Document[],
  arrayFilters?: Document[],
  hint?: Document | string,
  collation?: Document,
  upsert: boolean
}

Update Many

Note that write errors occuring with an update many model present are not retryable.

{
  namespace: '<db>.<collection>',
  name: 'updateMany',
  filter: Document,
  update: Document | Document[],
  arrayFilters?: Document[],
  hint?: Document | string,
  collation?: Document,
  upsert: boolean
}

Replace One

{
  namespace: '<db>.<collection>',
  name: 'replaceOne',
  filter: Document,
  replacement: Document,
  hint?: Document | string,
  collation?: Document
}

Delete One

{
  namespace: '<db>.<collection>',
  name: 'deleteOne',
  filter: Document,
  hint?: Document | string,
  collation?: Document
}

Delete Many

Note that write errors occuring with a delete many model present are not retryable.*

{
  namespace: '<db>.<collection>',
  name: 'deleteMany',
  filter: Document,
  hint?: Document | string,
  collation?: Document
}

Example

Below is a mixed model example of using the new API:

const client = new MongoClient(process.env.MONGODB_URI);
const models = [
  {
    name: 'insertOne',
    namespace: 'db.authors',
    document: { name: 'King' }
  },
  {
    name: 'insertOne',
    namespace: 'db.books',
    document: { name: 'It' }
  },
  {
    name: 'updateOne',
    namespace: 'db.books',
    filter: { name: 'it' },
    update: { $set: { year: 1986 } }
  }
];
const result = await client.bulkWrite(models);

The bulk write specific options that can be provided to the API are as follows:

  • ordered: Optional boolean that indicates the bulk write as ordered. Defaults to true.
  • verboseResults: Optional boolean to indicate to provide verbose results. Defaults to false.
  • bypassDocumentValidation: Optional boolean to bypass document validation rules. Defaults to false.
  • let: Optional document of parameter names and values that can be accessed using $$var. No default.

The object returned by the bulk write API is:

interface ClientBulkWriteResult {
  // Whether the bulk write was acknowledged.
  readonly acknowledged: boolean;
  // The total number of documents inserted across all insert operations.
  readonly insertedCount: number;
  // The total number of documents upserted across all update operations.
  readonly upsertedCount: number;
  // The total number of documents matched across all update operations.
  readonly matchedCount: number;
  // The total number of documents modified across all update operations.
  readonly modifiedCount: number;
  // The total number of documents deleted across all delete operations.
  readonly deletedCount: number;
  // The results of each individual insert operation that was successfully performed.
  // Note the keys in the map are the associated index in the models array.
  readonly insertResults?: ReadonlyMap<number, ClientInsertOneResult>;
  // The results of each individual update operation that was successfully performed.
  // Note the keys in the map are the associated index in the models array.
  readonly updateResults?: ReadonlyMap<number, ClientUpdateResult>;
  // The results of each individual delete operation that was successfully performed.
  // Note the keys in the map are the associated index in the models array.
  readonly deleteResults?: ReadonlyMap<number, ClientDeleteResult>;
}

Error Handling

Server side errors encountered during a bulk write will throw a MongoClientBulkWriteError. This error
has the following properties:

  • writeConcernErrors: Ann array of documents for each write concern error that occurred.
  • writeErrors: A map of index pointing at the models provided and the individual write error.
  • partialResult: The client bulk write result at the point where the error was thrown.

Schema assertion support

interface Book {
  name: string;
  authorName: string;
}

interface Author {
  name: string;
}

type MongoDBSchemas = {
  'db.books': Book;
  'db.authors': Author;
}

const model: ClientBulkWriteModel<MongoDBSchemas> = {
  namespace: 'db.books'
  name: 'insertOne',
  document: { title: 'Practical MongoDB Aggregations', authorName: 3 } 
  // error `authorName` cannot be number
};

Notice how authorName is type checked against the Book type because namespace is set to "db.books".

Double check the following

  • Ran npm run check:lint script
  • Self-review completed using the steps outlined here
  • PR title follows the correct format: type(NODE-xxxx)[!]: description
    • Example: feat(NODE-1234)!: rewriting everything in coffeescript
  • Changes are covered by tests
  • New TODOs have a related JIRA ticket

@durran durran force-pushed the NODE-6350-ts-clientBulkWrite branch from f31fc03 to 8b309e2 Compare October 14, 2024 19:00
@durran durran marked this pull request as ready for review October 16, 2024 08:12
@nbbeeken nbbeeken self-assigned this Oct 16, 2024
@nbbeeken nbbeeken added the Primary Review In Review with primary reviewer, not yet ready for team's eyes label Oct 16, 2024
@nbbeeken
Copy link
Contributor Author

evergreen refresh

Copy link
Contributor Author

@nbbeeken nbbeeken left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I forgot this is my PR.. LGTM! @durran

@nbbeeken nbbeeken added Team Review Needs review from team and removed Primary Review In Review with primary reviewer, not yet ready for team's eyes labels Oct 16, 2024
src/mongo_client.ts Show resolved Hide resolved
src/operations/client_bulk_write/common.ts Outdated Show resolved Hide resolved
src/operations/client_bulk_write/results_merger.ts Outdated Show resolved Hide resolved
test/types/client_bulk_write.test-d.ts Outdated Show resolved Hide resolved
test/types/client_bulk_write.test-d.ts Outdated Show resolved Hide resolved
test/types/client_bulk_write.test-d.ts Show resolved Hide resolved
test/types/client_bulk_write.test-d.ts Show resolved Hide resolved
test/types/client_bulk_write.test-d.ts Outdated Show resolved Hide resolved
test/types/client_bulk_write.test-d.ts Show resolved Hide resolved
@durran
Copy link
Member

durran commented Oct 17, 2024

evergreen retry

@durran durran merged commit 30c61f2 into main Oct 20, 2024
28 of 30 checks passed
@durran durran deleted the NODE-6350-ts-clientBulkWrite branch October 20, 2024 22:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Team Review Needs review from team
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants